go_clipper2

package module
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2025 License: BSL-1.0 Imports: 7 Imported by: 0

README

Go Clipper2

test codecov

A high-performance pure Go port of Clipper2, the industry-standard polygon clipping and offsetting library. Go Clipper2 provides robust geometric operations with 64-bit integer precision, eliminating floating-point numerical errors common in computational geometry.

🌟 Features

  • 🚀 Pure Go Implementation: Zero C/C++ dependencies for production use
  • 🎯 Complete API: All Clipper2 operations including boolean ops, offsetting, and clipping
  • 🧪 Comprehensive Testing: Property-based testing with different cases
  • 📦 Easy Integration: Simple Go module with clean, idiomatic API
Prerequisites
  • Go 1.23 or later
Installation
go get github.com/bolom009/go-clipper2

📖 Usage Examples

Basic Boolean Operations
package main

import (
    "fmt"
    goclipper2 "github.com/bolom009/go-clipper2"
)

func main() {
    // Define two overlapping rectangles
	var (
		subject = goclipper2.Paths64{
			{{0, 0}, {100, 0}, {100, 100}, {0, 100}},
		}
		clip = goclipper2.Paths64{
			{{50, 50}, {150, 50}, {150, 150}, {50, 150}},
		}
	)

	// wrapped method booleanOp (simplify usage of lib)
	unionResults := goclipper2.UnionWithClipPaths64(subject, clip, goclipper2.NonZero)
	fmt.Printf("Union area: %v\n", unionResults)
	
	// booleanOp
	unionResults = goclipper2.BooleanOpPaths64(goclipper2.Union, subject, clip, goclipper2.NonZero)
    fmt.Printf("Union area: %v\n", unionResults)
	
	/*
	    goclipper2.UnionPaths64(...)
	    goclipper2.UnionWithClipPaths64(...)
	    goclipper2.IntersectWithClipPaths64(...)
	    goclipper2.DifferenceWithClipPaths64(...)
	    goclipper2.XorWithClipPaths64(...)
	    goclipper2.UnionWithClipPathsD(...)
	    ...
	*/
}

📊 Implementation Status

Feature Status
Boolean Operations {64,D}
Union64, UnionD
Intersect64, IntersectD
Difference64, DifferenceD
Xor64, XorD
Polygon Offsetting
Rectangle Clipping
Area Calculation
Orientation Detection
Path Reversal
Minkowski Operations
PolyTree, PolyPath {64, D}
ZCallback

Legend: ✅ Implemented, ❌ Not implemented, 🚧 In progress

Performance Tips
  • Use integer coordinates when possible (more robust than float64)
  • For simple rectangular clipping, use RectClip64 instead of boolean operations
  • Pre-simplify complex polygons before operations
  • Consider polygon orientation for optimal performance

📄 License

This project is licensed under the Boost Software License 1.0, the same as the original Clipper2 library. See LICENSE for details.

Documentation

Index

Constants

View Source
const (
	ToEven = iota
	AwayFromZero
)
View Source
const (
	None      VertexFlags = 0
	OpenStart             = 1
	OpenEnd               = 2
	LocalMax              = 4
	LocalMin              = 8
)
View Source
const (
	MaxInt64 = int64(9223372036854775807)
	MaxCoord = MaxInt64 / 4

	Invalid64 = MaxInt64
)
View Source
const (
	Tolerance float64 = 1.0e-12
)

Variables

View Source
var (
	ErrPrecisionRange         = errors.New("precision is out of range")
	ErrInvalidRemoveListIndex = errors.New("invalid remove index from list")
)

Functions

func Area64

func Area64(path Path64) float64

func AreaD

func AreaD(path PathD) float64

func AreaPaths64

func AreaPaths64(paths Paths64) float64

func AreaPathsD

func AreaPathsD(paths PathsD) float64

func CrossProduct

func CrossProduct(pt1, pt2, pt3 Point64) float64

CrossProduct for three Point64 (pt1->pt2 x pt2->pt3)

func IsOdd

func IsOdd(val int) bool

func IsPositive64

func IsPositive64(poly Path64) bool

func IsPositiveD

func IsPositiveD(poly PathD) bool

func NewClipper64

func NewClipper64() *clipper64

func NewClipperD

func NewClipperD(decimalPrecision int) *clipperD

func Path2ContainsPath1

func Path2ContainsPath1(path1, path2 Path64) bool

func PerpendicDistFromLineSqr64

func PerpendicDistFromLineSqr64(pt, line1, line2 Point64) float64

func PerpendicDistFromLineSqrD

func PerpendicDistFromLineSqrD(pt, line1, line2 PointD) float64

func PointsNearEqual

func PointsNearEqual(pt1, pt2 PointD, distanceSqrd float64) bool

func ReversePath added in v1.0.1

func ReversePath[T any](p []T) []T

func SwapFrontBackSides

func SwapFrontBackSides(outrec *OutRec)

Types

type Active

type Active struct {
	// contains filtered or unexported fields
}

type ClipType

type ClipType uint8

ClipType specifies the type of boolean operation

const (
	NoClip       ClipType = iota
	Intersection          // intersect subject and clip polygons
	Union                 // union (OR) subject and clip polygons
	Difference            // subtract clip polygons from subject polygons
	Xor                   // exclusively or (XOR) subject and clip polygons
)

type ClipperOffset

type ClipperOffset struct {
	ArcTolerance      float64
	MergeGroups       bool
	MiterLimit        float64
	PreserveCollinear bool
	ReverseSolution   bool
	// contains filtered or unexported fields
}

func NewClipperOffset

func NewClipperOffset(miterLimit, arcTolerance float64, preserveCollinear, reverseSolution bool) *ClipperOffset

func (*ClipperOffset) AddPaths

func (co *ClipperOffset) AddPaths(paths Paths64, joinType JoinType, endType EndType)

func (*ClipperOffset) CalcSolutionCapacity

func (co *ClipperOffset) CalcSolutionCapacity() int

func (*ClipperOffset) CheckPathsReversed

func (co *ClipperOffset) CheckPathsReversed() bool

func (*ClipperOffset) Execute64

func (co *ClipperOffset) Execute64(delta float64, solution *Paths64)

func (*ClipperOffset) SetDeltaCallback added in v1.3.0

func (co *ClipperOffset) SetDeltaCallback(deltaCallback *DeltaCallbackFunc)

type DeltaCallbackFunc added in v1.3.0

type DeltaCallbackFunc func(path *Path64, path_normals *PathD, curr_idx uint8, prev_idx uint8) float64

type EndType

type EndType uint8
const (
	Polygon EndType = iota
	Joined
	Butt
	SquareET
	RoundET
)

type FillRule

type FillRule uint8

FillRule specifies how to determine polygon interiors for self-intersecting polygons

const (
	EvenOdd  FillRule = iota // odd numbered sub-regions are filled
	NonZero                  // non-zero sub-regions are filled
	Positive                 // positive sub-regions are filled
	Negative                 // negative sub-regions are filled
)

type Group

type Group struct {
	// contains filtered or unexported fields
}

func NewGroup

func NewGroup(paths Paths64, joinType JoinType, endTypeVal ...EndType) *Group

func (*Group) GetLowestPathInfo

func (g *Group) GetLowestPathInfo() (int, bool)

type HorzJoin

type HorzJoin struct {
	// contains filtered or unexported fields
}

func NewHorzJoin

func NewHorzJoin(ltor *OutPt, rtol *OutPt) *HorzJoin

type HorzSegment

type HorzSegment struct {
	// contains filtered or unexported fields
}

func NewHorzSegment

func NewHorzSegment(op *OutPt) *HorzSegment

type InflateOption added in v1.2.1

type InflateOption func(*inflateConfig)

func WithArcTolerance added in v1.2.1

func WithArcTolerance(tolerance float64) InflateOption

func WithMitterLimit added in v1.2.1

func WithMitterLimit(limit float64) InflateOption

func WithPrecision added in v1.2.1

func WithPrecision(precision int) InflateOption

type IntersectNode

type IntersectNode struct {
	// contains filtered or unexported fields
}

func NewIntersectNode

func NewIntersectNode(pt Point64, edge1 *Active, edge2 *Active) *IntersectNode

type JoinType

type JoinType uint8
const (
	Miter JoinType = iota
	Square
	Bevel
	Round
)

type JoinWith

type JoinWith uint8
const (
	JoinNone JoinWith = iota
	JoinLeft
	JoinRight
)

type LocalMinima

type LocalMinima struct {
	Vertex   *Vertex
	PolyType PathType
	IsOpen   bool
}

func NewLocalMinima

func NewLocalMinima(vertex *Vertex, polytype PathType, isOpen bool) *LocalMinima

func (*LocalMinima) Equals

func (l *LocalMinima) Equals(r *LocalMinima) bool

type Location added in v1.1.0

type Location int8
const (
	Left Location = iota
	Top
	Right
	Bottom
	Inside
)

type MidpointRounding

type MidpointRounding uint8

type OutPt

type OutPt struct {
	// contains filtered or unexported fields
}

type OutPt2 added in v1.1.0

type OutPt2 struct {
	// contains filtered or unexported fields
}

func NewOutPt2 added in v1.1.0

func NewOutPt2(pt Point64) *OutPt2

type OutRec

type OutRec struct {
	// contains filtered or unexported fields
}

type Path64

type Path64 []Point64

Path64 represents a sequence of points forming a path

func Ellipse64

func Ellipse64(center Point64, radiusX, radiusY float64, steps int) Path64

func MakePath64 added in v1.0.1

func MakePath64(vals ...int64) Path64

func OffsetPath

func OffsetPath(path Path64, dx, dy int64) Path64

func PathDToPath64

func PathDToPath64(path PathD) Path64

func ScalePath64

func ScalePath64(path Path64, scale float64) Path64

func ScalePathDToPath64

func ScalePathDToPath64(path PathD, scale float64) Path64

func SimplifyPath64 added in v1.1.0

func SimplifyPath64(path Path64, epsilon float64, isClosedPath bool) Path64

func StripDuplicates

func StripDuplicates(path Path64, isClosedPath bool) Path64

func TranslatePath64 added in v1.1.0

func TranslatePath64(path Path64, dx, dy int64) Path64

func TrimCollinear64 added in v1.1.0

func TrimCollinear64(path Path64, isOpen bool) Path64

type PathD

type PathD []PointD

PathD represents a sequence of points forming a path

func EllipseD

func EllipseD(center PointD, radiusX, radiusY float64, steps int) PathD

func MakePathD added in v1.0.1

func MakePathD(vals ...float64) PathD

func Path64ToPathD

func Path64ToPathD(path Path64) PathD

func ScalePath64ToPathD

func ScalePath64ToPathD(path Path64, scale float64) PathD

func ScalePathD

func ScalePathD(path PathD, scale float64) PathD

func SimplifyPathD added in v1.1.0

func SimplifyPathD(path PathD, epsilon float64, isClosedPath bool) PathD

func TranslatePathD added in v1.1.0

func TranslatePathD(path PathD, dx, dy float64) PathD

func TrimCollinearD added in v1.1.0

func TrimCollinearD(path PathD, precision int, isOpen bool) PathD

type PathType

type PathType uint8
const (
	Subject PathType = iota
	Clip
)

type Paths64

type Paths64 []Path64

Paths64 represents a collection of paths

func BooleanOpPaths64

func BooleanOpPaths64(clipType ClipType, subject Paths64, clip Paths64, fillRule FillRule) Paths64

func DifferenceWithClipPaths64

func DifferenceWithClipPaths64(subject, clip Paths64, fillRule FillRule) Paths64

func InflatePaths64

func InflatePaths64(paths Paths64, delta float64, joinType JoinType, endType EndType, opts ...InflateOption) Paths64

func IntersectWithClipPaths64

func IntersectWithClipPaths64(subject, clip Paths64, fillRule FillRule) Paths64

func MinkowskiDiff64

func MinkowskiDiff64(pattern, path Path64, isClosed bool) Paths64

func MinkowskiSum64

func MinkowskiSum64(pattern, path Path64, isClosed bool) Paths64

func PathsDToPaths64

func PathsDToPaths64(path PathsD) Paths64

func RectClipLinesPath64 added in v1.1.0

func RectClipLinesPath64(rect Rect64, path Path64) Paths64

func RectClipLinesPaths64 added in v1.1.0

func RectClipLinesPaths64(rect Rect64, paths Paths64) Paths64

func RectClipPath64 added in v1.1.0

func RectClipPath64(rect Rect64, path Path64) Paths64

func RectClipPaths64 added in v1.1.0

func RectClipPaths64(rect Rect64, paths Paths64) Paths64

func ScalePathsDToPaths64

func ScalePathsDToPaths64(paths PathsD, scale float64) Paths64

func SimplifyPaths64 added in v1.1.0

func SimplifyPaths64(paths Paths64, epsilon float64, isClosedPaths bool) Paths64

func TranslatePaths64 added in v1.1.0

func TranslatePaths64(paths Paths64, dx, dy int64) Paths64

func UnionPaths64

func UnionPaths64(subject Paths64, fillRule FillRule) Paths64

func UnionWithClipPaths64

func UnionWithClipPaths64(subject, clip Paths64, fillRule FillRule) Paths64

func XorWithClipPaths64

func XorWithClipPaths64(subject, clip Paths64, fillRule FillRule) Paths64

type PathsD

type PathsD []PathD

PathsD represents a collection of paths

func BooleanOpPathsD

func BooleanOpPathsD(clipType ClipType, subject PathsD, clip PathsD, fillRule FillRule, precisionV ...int) PathsD

func DifferenceWithClipPathsD

func DifferenceWithClipPathsD(subject, clip PathsD, fillRule FillRule, precision ...int) PathsD

func InflatePathsD

func InflatePathsD(paths PathsD, delta float64, joinType JoinType, endType EndType, opts ...InflateOption) PathsD

func IntersectWithClipPathsD

func IntersectWithClipPathsD(subject, clip PathsD, fillRule FillRule, precision ...int) PathsD

func MinkowskiDiffD

func MinkowskiDiffD(pattern, path PathD, isClosed bool, precisionV ...int) PathsD

func MinkowskiSumD

func MinkowskiSumD(pattern, path PathD, isClosed bool, precisionV ...int) PathsD

func Paths64ToPathsD

func Paths64ToPathsD(path Paths64) PathsD

func RectClipLinesPathD added in v1.1.0

func RectClipLinesPathD(rect RectD, path PathD) PathsD

func RectClipLinesPathsD added in v1.1.0

func RectClipLinesPathsD(rect RectD, paths PathsD, precisionV ...int) PathsD

func RectClipPathD added in v1.1.0

func RectClipPathD(rect RectD, path PathD) PathsD

func RectClipPathsD added in v1.1.0

func RectClipPathsD(rect RectD, paths PathsD, precisionV ...int) PathsD

func ScalePaths64ToPathsD

func ScalePaths64ToPathsD(paths Paths64, scale float64) PathsD

func SimplifyPathsD added in v1.1.0

func SimplifyPathsD(paths PathsD, epsilon float64, isClosedPaths bool) PathsD

func TranslatePathsD added in v1.1.0

func TranslatePathsD(paths PathsD, dx, dy float64) PathsD

func UnionPathsD

func UnionPathsD(subject PathsD, fillRule FillRule, precision ...int) PathsD

func UnionWithClipPathsD

func UnionWithClipPathsD(subject, clip PathsD, fillRule FillRule, precision ...int) PathsD

func XorWithClipPathsD

func XorWithClipPathsD(subject, clip PathsD, fillRule FillRule, precision ...int) PathsD

type Point64

type Point64 struct {
	X, Y int64
}

Point64 represents a point with 64-bit integer coordinates

func NewFloatPoint64

func NewFloatPoint64(x, y float64) Point64

func (*Point64) Add

func (p *Point64) Add(p2 Point64)

func (*Point64) Equals

func (p *Point64) Equals(p2 Point64) bool

func (*Point64) NEquals

func (p *Point64) NEquals(p2 Point64) bool

func (*Point64) Sub

func (p *Point64) Sub(p2 Point64)

func (*Point64) ToPoint64

func (p *Point64) ToPoint64(pt PointD) Point64

func (*Point64) ToPointD

func (p *Point64) ToPointD() PointD

func (*Point64) ToPointDScale

func (p *Point64) ToPointDScale(scale float64) PointD

type PointD

type PointD struct {
	X, Y float64
}

func (*PointD) Equals

func (p *PointD) Equals(p2 PointD) bool

func (*PointD) NEquals

func (p *PointD) NEquals(p2 PointD) bool

func (*PointD) Negate

func (p *PointD) Negate()

func (*PointD) Scale

func (p *PointD) Scale(scale float64)

func (*PointD) ToPoint64

func (p *PointD) ToPoint64() Point64

func (*PointD) ToPoint64Scale

func (p *PointD) ToPoint64Scale(scale float64) Point64

type PointInPolygonResult

type PointInPolygonResult uint8
const (
	IsOn PointInPolygonResult = iota
	IsInside
	IsOutside
)

func PointInPolygon added in v1.1.0

func PointInPolygon(pt Point64, polygon Path64) PointInPolygonResult

type PolyPath64 added in v1.1.5

type PolyPath64 struct {
	*PolyPathBase
}

type PolyPathBase

type PolyPathBase struct {
	// contains filtered or unexported fields
}

func NewPolyPathBase

func NewPolyPathBase(parent *PolyPathBase) *PolyPathBase

func (*PolyPathBase) AddChild

func (p *PolyPathBase) AddChild(pth Path64) *PolyPathBase

func (*PolyPathBase) Clear

func (p *PolyPathBase) Clear()

func (*PolyPathBase) Count added in v1.1.5

func (p *PolyPathBase) Count() int

func (*PolyPathBase) GetChildren

func (p *PolyPathBase) GetChildren() []*PolyPathBase

func (*PolyPathBase) IsHole

func (p *PolyPathBase) IsHole() bool

func (*PolyPathBase) Level

func (p *PolyPathBase) Level() int

func (*PolyPathBase) Scale added in v1.1.5

func (p *PolyPathBase) Scale() float64

func (*PolyPathBase) SetScale added in v1.1.5

func (p *PolyPathBase) SetScale(scale float64)

func (*PolyPathBase) ToString added in v1.1.5

func (p *PolyPathBase) ToString() string

func (*PolyPathBase) ToStringInternal added in v1.1.5

func (p *PolyPathBase) ToStringInternal(idx, level int) string

type PolyPathD added in v1.1.5

type PolyPathD struct {
	*PolyPathBase
}

type PolyTree64 added in v1.1.5

type PolyTree64 PolyPath64

func BooleanOpPolyTree64 added in v1.2.0

func BooleanOpPolyTree64(clipType ClipType, subject Paths64, clip Paths64, fillRule FillRule) *PolyTree64

func NewPolyTree64 added in v1.1.5

func NewPolyTree64() *PolyTree64

type PolyTreeD added in v1.1.5

type PolyTreeD PolyPathD

func BooleanOpPolyTreeD added in v1.1.5

func BooleanOpPolyTreeD(clipType ClipType, subject PathsD, clip PathsD, fillRule FillRule, precisionV ...int) *PolyTreeD

func NewPolyTreeD added in v1.1.5

func NewPolyTreeD() *PolyTreeD

type Rect64

type Rect64 struct {
	// contains filtered or unexported fields
}

func GetBounds64

func GetBounds64(path Path64) Rect64

func NewRect64

func NewRect64(left, top, right, bottom int64) Rect64

func NewRect64Invalid

func NewRect64Invalid(isValid bool) Rect64

func ScaleRect64

func ScaleRect64(rec Rect64, scale float64) Rect64

func ScaleRectD added in v1.1.0

func ScaleRectD(rec RectD, scale float64) Rect64

func (*Rect64) AsPath

func (r *Rect64) AsPath() Path64

func (*Rect64) Contains

func (r *Rect64) Contains(rec Rect64) bool

func (*Rect64) Intersects

func (r *Rect64) Intersects(rec Rect64) bool

func (*Rect64) IsEmpty

func (r *Rect64) IsEmpty() bool

func (*Rect64) IsInvalid

func (r *Rect64) IsInvalid() bool

func (*Rect64) MidPoint

func (r *Rect64) MidPoint() Point64

type RectClip64 added in v1.1.0

type RectClip64 struct {
	// contains filtered or unexported fields
}

func NewRectClip64 added in v1.1.0

func NewRectClip64(rect Rect64, getPathV ...func(op *OutPt2) Path64) *RectClip64

func (*RectClip64) Execute added in v1.1.0

func (r *RectClip64) Execute(paths Paths64) Paths64

type RectClipLines64 added in v1.1.0

type RectClipLines64 struct {
	*RectClip64
}

func NewRectClipLines64 added in v1.1.0

func NewRectClipLines64(rect Rect64) *RectClipLines64

type RectD

type RectD struct {
	// contains filtered or unexported fields
}

func NewRectD

func NewRectD(left, top, right, bottom float64) RectD

func NewRectDInvalid

func NewRectDInvalid(isValid bool) RectD

func (*RectD) AsPath

func (r *RectD) AsPath() PathD

func (*RectD) Contains

func (r *RectD) Contains(rec RectD) bool

func (*RectD) Intersects

func (r *RectD) Intersects(rec RectD) bool

func (*RectD) IsEmpty

func (r *RectD) IsEmpty() bool

func (*RectD) IsInvalid

func (r *RectD) IsInvalid() bool

func (*RectD) MidPoint

func (r *RectD) MidPoint() PointD

type UInt128Struct

type UInt128Struct struct {
	Lo64 uint64
	Hi64 uint64
}

type Vertex

type Vertex struct {
	// contains filtered or unexported fields
}

func NewVertex

func NewVertex(pt Point64, flags VertexFlags, prev *Vertex) *Vertex

type VertexFlags

type VertexFlags uint8

type VertexPoolList

type VertexPoolList []*Vertex

func (*VertexPoolList) Add

func (vpl *VertexPoolList) Add(pt Point64, flags VertexFlags, prev *Vertex) *Vertex

func (*VertexPoolList) EnsureCapacity

func (vpl *VertexPoolList) EnsureCapacity(nCap int)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL