### Install BezierKit with CocoaPods Source: https://github.com/hfutrell/bezierkit/blob/master/README.md Use this command to install the CocoaPods dependency manager. Add BezierKit to your Podfile and run 'pod install'. ```bash $ gem install cocoapods ``` ```ruby target '' do pod 'BezierKit', '>= 0.16.3' end ``` ```bash $ pod install ``` -------------------------------- ### Install BezierKit with Swift Package Manager Source: https://context7.com/hfutrell/bezierkit/llms.txt Add BezierKit to your project's dependencies using Swift Package Manager by specifying the repository URL and version. ```swift // Package.swift // swift-tools-version:5.0 import PackageDescription let package = Package( name: "MyApp", dependencies: [ .package(url: "https://github.com/hfutrell/BezierKit.git", from: "0.16.3"), ], targets: [ .target(name: "MyApp", dependencies: ["BezierKit"]) ] ) ``` -------------------------------- ### Install BezierKit with CocoaPods Source: https://context7.com/hfutrell/bezierkit/llms.txt Integrate BezierKit into your iOS or macOS project using CocoaPods by adding the gem to your Podfile. ```ruby # Podfile target 'MyApp' do pod 'BezierKit', '>= 0.16.3' end ``` -------------------------------- ### Get Bezier Curve Bounding Box Source: https://github.com/hfutrell/bezierkit/blob/master/README.md Retrieves the bounding box of a Bezier curve. This is useful for rendering or spatial queries. Assumes curve and context are initialized. ```swift let boundingBox = curve.boundingBox Draw.drawSkeleton(context, curve: curve) Draw.drawCurve(context, curve: curve) Draw.setColor(context, color: Draw.pinkish) Draw.drawBoundingBox(context, boundingBox: curve.boundingBox) ``` -------------------------------- ### Split Bezier Curve by Range Source: https://github.com/hfutrell/bezierkit/blob/master/README.md Splits a Bezier curve into a subcurve defined by a start and end t-value. Ensure the context and drawing utilities are set up before use. ```swift Draw.setColor(context, color: Draw.lightGrey) Draw.drawSkeleton(context, curve: curve) Draw.drawCurve(context, curve: curve) let subcurve = curve.split(from: 0.25, to: 0.75) // or try (leftCurve, rightCurve) = curve.split(at:) Draw.setColor(context, color: Draw.red) Draw.drawCurve(context, curve: subcurve) Draw.drawCircle(context, center: curve.point(at: 0.25), radius: 3) Draw.drawCircle(context, center: curve.point(at: 0.75), radius: 3) ``` -------------------------------- ### Get Bounding Box and Perform Spatial Queries Source: https://context7.com/hfutrell/bezierkit/llms.txt Access the boundingBox property for the tightest axis-aligned bounding box. Use contains(), overlaps(), and intersection() for spatial queries. CoreGraphics drawing functions are also provided. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 100, y: 25), p1: CGPoint(x: 10, y: 90), p2: CGPoint(x: 110, y: 100), p3: CGPoint(x: 150, y: 195) ) let box: BoundingBox = curve.boundingBox print("min: \(box.min), max: \(box.max)") // e.g. min: (39.0, 25.0), max: (150.0, 195.0) print("as CGRect: \(box.cgRect)") let testPoint = CGPoint(x: 100, y: 100) print("contains point: \(box.contains(testPoint))") // true or false let otherBox = BoundingBox(p1: CGPoint(x: 0, y: 0), p2: CGPoint(x: 80, y: 80)) print("overlaps: \(box.overlaps(otherBox))") print("intersection: \(box.intersection(otherBox))") // Draw it using CoreGraphics let context: CGContext = ... Draw.drawCurve(context, curve: curve) Draw.setColor(context, color: Draw.pinkish) Draw.drawBoundingBox(context, boundingBox: box) ``` -------------------------------- ### Find Intersections Between Bezier Curves in Swift Source: https://github.com/hfutrell/bezierkit/blob/master/README.md Use the intersections(with:) method to find intersections between two Bezier curves. The result contains t-values for each curve, which can be used with point(at:) to get the intersection coordinates. ```swift let intersections: [Intersection] = curve1.intersections(with: curve2) let points: [CGPoint] = intersections.map { curve1.point(at: $0.t1) } Draw.drawCurve(context, curve: curve1) Draw.drawCurve(context, curve: curve2) for p in points { Draw.drawPoint(context, origin: p) } ``` -------------------------------- ### Get Extrema T-Values of a Cubic Curve Source: https://context7.com/hfutrell/bezierkit/llms.txt Use `extrema()` to find the t-values where a cubic curve reaches its maximum or minimum x and y coordinates. These are used internally for bounding box calculations. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 200, y: 300), p2: CGPoint(x: -100, y: 200), p3: CGPoint(x: 100, y: 0) ) let extrema = curve.extrema() print("x extrema t-values: \(extrema.x)") // t-values for x-axis extrema print("y extrema t-values: \(extrema.y)") // t-values for y-axis extrema print("all extrema t-values: \(extrema.all)") // Get the actual points at those t-values let extremaPoints = extrema.all.map { curve.point(at: $0) } print("extrema points: \(extremaPoints)") ``` -------------------------------- ### Construct and Draw Bezier Curves in Swift Source: https://github.com/hfutrell/bezierkit/blob/master/README.md Import BezierKit and use CubicCurve, QuadraticCurve, or LineSegment to create curves. Use Draw.drawSkeleton and Draw.drawCurve to visualize them. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 100, y: 25), p1: CGPoint(x: 10, y: 90), p2: CGPoint(x: 110, y: 100), p3: CGPoint(x: 150, y: 195) ) let context: CGContext = ... // your graphics context here Draw.drawSkeleton(context, curve) // draws visual representation of curve control points Draw.drawCurve(context, curve) // draws the curve itself ``` -------------------------------- ### Construct Bézier Curves in Swift Source: https://context7.com/hfutrell/bezierkit/llms.txt Initialize CubicCurve, QuadraticCurve, and LineSegment objects with their respective control points. CubicCurve also supports construction through a point-on-curve initializer and conversion from lower-order curves. ```swift import BezierKit // Cubic Bézier curve with four control points let cubic = CubicCurve( p0: CGPoint(x: 100, y: 25), p1: CGPoint(x: 10, y: 90), p2: CGPoint(x: 110, y: 100), p3: CGPoint(x: 150, y: 195) ) // Quadratic Bézier curve with three control points let quadratic = QuadraticCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 50, y: 100), p2: CGPoint(x: 100, y: 0) ) // Line segment let line = LineSegment( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 200, y: 200) ) // CubicCurve through a known intermediate point at t=0.5 let fittedCurve = CubicCurve( start: CGPoint(x: 0, y: 0), end: CGPoint(x: 200, y: 0), mid: CGPoint(x: 100, y: 80), t: 0.5 ) // Convert a lower-order curve up to CubicCurve let cubicFromLine = CubicCurve(lineSegment: line) let cubicFromQuad = CubicCurve(quadratic: quadratic) ``` -------------------------------- ### Path and PathComponent Construction and Manipulation Source: https://context7.com/hfutrell/bezierkit/llms.txt Create `PathComponent` from curves and `Path` from components. Convert between `Path` and `CGPath`, perform containment tests, offsetting, splitting, and intersection checks. ```swift import BezierKit // Build a PathComponent from an array of curves let c1 = CubicCurve(p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 50, y: 100), p2: CGPoint(x: 100, y: 100), p3: CGPoint(x: 150, y: 0)) let c2 = LineSegment(p0: CGPoint(x: 150, y: 0), p1: CGPoint(x: 0, y: 0)) let component = PathComponent(curves: [c1, c2]) // closed triangle-like shape print("isClosed: \(component.isClosed)") // true print("length: \(component.length)") print("elements: \(component.numberOfElements)") // Wrap into a Path and convert to CGPath for drawing let path = Path(components: [component]) let cgPath: CGPath = path.cgPath // ready for use in CoreGraphics / SwiftUI // Build a Path directly from a CGPath let rect = CGPath(rect: CGRect(x: 0, y: 0, width: 100, height: 100), transform: nil) let rectPath = Path(cgPath: rect) // Containment test print("contains point: \(path.contains(CGPoint(x: 75, y: 10)))") // Offset entire path let expandedPath: Path = path.offset(distance: 5) // Split a PathComponent over a range of locations let start = IndexedPathComponentLocation(elementIndex: 0, t: 0.2) let end = IndexedPathComponentLocation(elementIndex: 0, t: 0.8) let subcomponent = component.split(from: start, to: end) // Intersections between two PathComponents let otherComponent = PathComponent(curve: LineSegment( p0: CGPoint(x: 0, y: 50), p1: CGPoint(x: 200, y: 50))) let componentIntersections = component.intersections(with: otherComponent) print("intersections: \(componentIntersections.count)") ``` -------------------------------- ### Curve Offsetting and Outlining Source: https://context7.com/hfutrell/bezierkit/llms.txt Provides methods to offset curves along their normals and create outlines. The `offset` method returns an array of approximating curves, while `outline` creates a closed PathComponent. Specific points can also be offset from the curve surface. ```APIDOC ## offset(distance:) ### Description Shifts a curve in the direction of its normals, returning an array of approximating curves. ### Method `offset(distance: Double) -> [BezierCurve]` ### offset(t: distance:) ### Description Gets a point offset from the curve surface at a specific t-value. ### Method `offset(t: Double, distance: Double) -> CGPoint` ## outline(distance:) ### Description Builds a closed `PathComponent` encompassing both sides of the curve with end caps. ### Method `outline(distance: Double) -> PathComponent` ## outline(distanceAlongNormal: distanceOppositeNormal:) ### Description Builds an asymmetric outline with different distances on each side. ### Method `outline(distanceAlongNormal: Double, distanceOppositeNormal: Double) -> PathComponent` ## outlineShapes(distance:) ### Description Gets the outline as discrete `Shape` objects for further manipulation. ### Method `outlineShapes(distance: Double) -> [Shape]` ``` -------------------------------- ### Project a Point onto a Bezier Curve or Path Source: https://context7.com/hfutrell/bezierkit/llms.txt Use `project(_:)` to find the closest point on a curve to a given 2D point and its corresponding t-value. For a `Path`, `project(_:)` returns an `IndexedPathLocation`. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 50, y: 200), p2: CGPoint(x: 150, y: 200), p3: CGPoint(x: 200, y: 0) ) let queryPoint = CGPoint(x: 100, y: 50) let result = curve.project(queryPoint) print("Nearest on-curve point: \(result.point)") // e.g. (100.0, 148.4) print("At t-value: \(result.t)") // e.g. 0.499 // For a Path, project returns an IndexedPathLocation let path = Path(curve: curve) if let pathResult = path.project(queryPoint) { print("Component index: \(pathResult.location.componentIndex)") print("Element index: \(pathResult.location.elementIndex)") print("t: \(pathResult.location.t)") print("Point: \(pathResult.point)") } // Fast proximity check without computing exact closest point let isNearby: Bool = path.pointIsWithinDistanceOfBoundary(queryPoint, distance: 30) print("Within 30 units of path boundary: \(isNearby)") ``` -------------------------------- ### Offsetting and Outlining Curves Source: https://context7.com/hfutrell/bezierkit/llms.txt Use `offset` to shift a curve along its normals and `outline` to create closed paths. `outlineShapes` provides discrete shapes for further manipulation. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 20, y: 100), p1: CGPoint(x: 80, y: 20), p2: CGPoint(x: 160, y: 20), p3: CGPoint(x: 220, y: 100) ) // Offset the curve outward by 20 points (returns [BezierCurve] approximation) let offsetCurves: [BezierCurve] = curve.offset(distance: 20) print("Offset produced \(offsetCurves.count) segment(s)") // Get a point offset from the curve surface at a specific t-value let offsetPoint: CGPoint = curve.offset(t: 0.5, distance: 20) print("Offset point at t=0.5: \(offsetPoint)") // Build a symmetric outline (closed PathComponent with end caps) let outline: PathComponent = curve.outline(distance: 15) print("Outline isClosed: \(outline.isClosed)") // Build an asymmetric outline (different distances on each side) let asymOutline: PathComponent = curve.outline(distanceAlongNormal: 20, distanceOppositeNormal: 5) // Get outline as discrete Shape objects for further manipulation let shapes: [Shape] = curve.outlineShapes(distance: 15) print("Shape count: \(shapes.count)") ``` -------------------------------- ### Drawing Curves and Paths with CoreGraphics Source: https://context7.com/hfutrell/bezierkit/llms.txt Utilize the Draw utility class to render BezierKit curves, paths, bounding boxes, and skeletons directly into a CGContext. Requires an active CGContext, typically obtained from a UIView or NSView drawing method. Various colors can be set for drawing elements. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 100, y: 25), p1: CGPoint(x: 10, y: 90), p2: CGPoint(x: 110, y: 100), p3: CGPoint(x: 150, y: 195) ) // Assumes you have a CGContext (e.g., from a UIView.draw(_:) or NSView.draw(_:)) let context: CGContext = UIGraphicsGetCurrentContext()! // Draw the curve's skeleton (control point handles) in light grey Draw.drawSkeleton(context, curve: curve) // Draw the curve itself with current stroke color Draw.drawCurve(context, curve: curve) // Highlight a specific point on the curve Draw.setColor(context, color: Draw.red) Draw.drawPoint(context, origin: curve.point(at: 0.5)) // Draw the precise bounding box Draw.setColor(context, color: Draw.pinkish) Draw.drawBoundingBox(context, boundingBox: curve.boundingBox) // Draw intersection markers let curve2 = CubicCurve(p0: CGPoint(x: 0, y: 100), p1: CGPoint(x: 200, y: 300), p2: CGPoint(x: 200, y: -100), p3: CGPoint(x: 400, y: 100)) let hits = curve.intersections(with: curve2) Draw.setColor(context, color: Draw.blue) for hit in hits { Draw.drawCircle(context, center: curve.point(at: hit.t1), radius: 5) } // Draw a full Path let path = Path(curve: curve) Draw.drawPath(context, path) ``` -------------------------------- ### Point Projection Source: https://context7.com/hfutrell/bezierkit/llms.txt The `project(_:)` method finds the nearest point on a curve to a given 2D point, returning the point and its corresponding t-value. For paths, it returns an `IndexedPathLocation` and offers a proximity check with `pointIsWithinDistanceOfBoundary(_:distance:)`. ```APIDOC ## Point Projection `project(_:)` finds the nearest on-curve point to any given 2D point, returning both the closest point and its `t` parameter value. Useful for snapping, hit-testing, and path-proximity queries. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 50, y: 200), p2: CGPoint(x: 150, y: 200), p3: CGPoint(x: 200, y: 0) ) let queryPoint = CGPoint(x: 100, y: 50) let result = curve.project(queryPoint) print("Nearest on-curve point: \(result.point)") // e.g. (100.0, 148.4) print("At t-value: \(result.t)") // e.g. 0.499 // For a Path, project returns an IndexedPathLocation let path = Path(curve: curve) if let pathResult = path.project(queryPoint) { print("Component index: \(pathResult.location.componentIndex)") print("Element index: \(pathResult.location.elementIndex)") print("t: \(pathResult.location.t)") print("Point: \(pathResult.point)") } // Fast proximity check without computing exact closest point let isNearby: Bool = path.pointIsWithinDistanceOfBoundary(queryPoint, distance: 30) print("Within 30 units of path boundary: \(isNearby)") ``` ``` -------------------------------- ### Evaluate Bézier Curve Geometry Source: https://context7.com/hfutrell/bezierkit/llms.txt Use point(at:), derivative(at:), and normal(at:) to evaluate curve geometry at a specific parameter t. The length() method computes the arc length, and lookupTable(steps:) generates evenly-spaced points. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 50, y: 100), p2: CGPoint(x: 150, y: 100), p3: CGPoint(x: 200, y: 0) ) let midPoint: CGPoint = curve.point(at: 0.5) // point on curve at t=0.5 let tangent: CGPoint = curve.derivative(at: 0.5) // tangent vector at t=0.5 let normal: CGPoint = curve.normal(at: 0.5) // unit normal at t=0.5 let curveLength: CGFloat = curve.length() // arc length via Legendre-Gauss quadrature // Generate a lookup table of 50 evenly-spaced t-value points let lut: [CGPoint] = curve.lookupTable(steps: 50) // Compute the convex hull at a given t let hullPoints: [CGPoint] = curve.hull(0.5) print("Mid-curve point: \(midPoint)") print("Arc length: \(curveLength)") ``` -------------------------------- ### Path and PathComponent Source: https://context7.com/hfutrell/bezierkit/llms.txt Defines `PathComponent` as an ordered sequence of contiguous `BezierCurve` elements and `Path` as a collection of `PathComponent` instances. These structures allow for building, manipulating, and converting complex shapes. ```APIDOC ## PathComponent(curves:) ### Description Initializes a `PathComponent` from an array of curves. ### Method `PathComponent(curves: [BezierCurve])` ## PathComponent(curve:) ### Description Initializes a `PathComponent` from a single curve. ### Method `PathComponent(curve: BezierCurve)` ## Path(components:) ### Description Initializes a `Path` from an array of `PathComponent` instances. ### Method `Path(components: [PathComponent])` ## Path(cgPath:) ### Description Initializes a `Path` from a `CGPath`. ### Method `Path(cgPath: CGPath)` ## cgPath ### Description Converts a `Path` to a `CGPath` for use in CoreGraphics or SwiftUI. ### Method `cgPath -> CGPath` ## contains(point:) ### Description Tests if a point is contained within the path. ### Method `contains(CGPoint) -> Bool` ## offset(distance:) ### Description Offsets an entire path by a given distance. ### Method `offset(distance: Double) -> Path` ## split(from: to:) ### Description Splits a `PathComponent` over a range of locations. ### Method `split(from: IndexedPathComponentLocation, to: IndexedPathComponentLocation) -> PathComponent` ## intersections(with:) ### Description Calculates the intersection points between two `PathComponent` instances. ### Method `intersections(with: PathComponent) -> [Double]` ``` -------------------------------- ### Split a Cubic Curve into Segments Source: https://context7.com/hfutrell/bezierkit/llms.txt Use `split(from:to:)` to extract a subcurve within a specified t-value range, or `split(at:)` to bisect the curve into two halves. The split point is consistent between the resulting halves. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 50, y: 150), p2: CGPoint(x: 150, y: 150), p3: CGPoint(x: 200, y: 0) ) // Extract the middle third of the curve let middle: CubicCurve = curve.split(from: 0.33, to: 0.66) // Split into two halves at t=0.5 let (leftHalf, rightHalf) = curve.split(at: 0.5) // The split point is consistent between both halves assert(leftHalf.endingPoint == rightHalf.startingPoint) print("left ends at: \(leftHalf.endingPoint)") // Draw only the middle segment let context: CGContext = ... Draw.setColor(context, color: Draw.lightGrey) Draw.drawCurve(context, curve: curve) Draw.setColor(context, color: Draw.red) Draw.drawCurve(context, curve: middle) Draw.drawCircle(context, center: curve.point(at: 0.33), radius: 4) Draw.drawCircle(context, center: curve.point(at: 0.66), radius: 4) ``` -------------------------------- ### Curve and Path Transformations Source: https://context7.com/hfutrell/bezierkit/llms.txt Apply immutable affine transformations (translate, rotate, scale) or reverse the direction of BezierKit curves and Paths. Both curve types and Path conform to Transformable and Reversible protocols. Transformations return new objects, leaving the originals unchanged. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 50, y: 100), p2: CGPoint(x: 150, y: 100), p3: CGPoint(x: 200, y: 0) ) // Apply an affine transform (translate, rotate, scale, etc.) let transform = CGAffineTransform(translationX: 50, y: 50) .rotated(by: .pi / 4) .scaledBy(x: 2, y: 2) let transformed: CubicCurve = curve.copy(using: transform) // Reverse the curve direction (p3 becomes p0, etc.) let reversed: CubicCurve = curve.reversed() assert(reversed.startingPoint == curve.endingPoint) assert(reversed.endingPoint == curve.startingPoint) // Transform an entire Path let path = Path(curve: curve) let movedPath: Path = path.copy(using: CGAffineTransform(translationX: 100, y: 0)) // Reverse all path components let reversedPath: Path = path.reversed() ``` -------------------------------- ### Add BezierKit as Swift Package Manager Dependency Source: https://github.com/hfutrell/bezierkit/blob/master/README.md Add BezierKit to your Swift package's dependencies in Package.swift. ```swift // swift-tools-version:5.0 import PackageDescription let package = Package( name: "", dependencies: [ .package(url: "https://github.com/hfutrell/BezierKit.git", from: "0.16.3"), ] ) ``` -------------------------------- ### Vector Boolean Operations on Paths Source: https://context7.com/hfutrell/bezierkit/llms.txt Perform boolean set operations (union, subtract, intersect, crossingsRemoved) on BezierKit Paths. These operations work on multi-contour closed paths and return a new Path. Also includes methods for splitting paths into disjoint components, testing containment, and finding intersection locations. ```swift import BezierKit // Create two overlapping rectangular paths let square = Path(cgPath: CGPath(rect: CGRect(x: 0, y: 0, width: 100, height: 100), transform: nil)) let circle = Path(cgPath: CGPath(ellipseIn: CGRect(x: 50, y: 50, width: 100, height: 100), transform: nil)) // Union: shape covering both areas let united: Path = square.union(circle) // Subtract: square minus the circle overlap let subtracted: Path = square.subtract(circle) // Intersect: only the overlapping area let intersection: Path = square.intersect(circle) // Remove self-crossing loops from a complex path let selfCrossingPath: Path = ... let cleaned: Path = selfCrossingPath.crossingsRemoved() // Split a Path with multiple components into disjoint sub-paths let compound = Path(components: square.components + circle.components) let disjoint: [Path] = compound.disjointComponents() print("Disjoint components: \(disjoint.count)") // Test containment of one path inside another print("square contains circle: \(square.contains(circle))") print("paths intersect: \(square.intersects(circle))") // Find exact intersection locations between two Paths let pathIntersections: [PathIntersection] = square.intersections(with: circle) for pi in pathIntersections { let p = square.point(at: pi.indexedPathLocation1) print("Intersection at path point: \(p)") } ``` -------------------------------- ### Splitting Curves Source: https://context7.com/hfutrell/bezierkit/llms.txt Curves can be split into subcurves or halves. `split(from:to:)` extracts a segment defined by a t-value range, while `split(at:)` divides the curve into two equal halves at a specified t-value. ```APIDOC ## Splitting Curves `split(from:to:)` produces a subcurve over a t-value range; `split(at:)` bisects a curve into left and right halves at a given t-value. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 50, y: 150), p2: CGPoint(x: 150, y: 150), p3: CGPoint(x: 200, y: 0) ) // Extract the middle third of the curve let middle: CubicCurve = curve.split(from: 0.33, to: 0.66) // Split into two halves at t=0.5 let (leftHalf, rightHalf) = curve.split(at: 0.5) // The split point is consistent between both halves assert(leftHalf.endingPoint == rightHalf.startingPoint) print("left ends at: \(leftHalf.endingPoint)") // Draw only the middle segment let context: CGContext = ... Draw.setColor(context, color: Draw.lightGrey) Draw.drawCurve(context, curve: curve) Draw.setColor(context, color: Draw.red) Draw.drawCurve(context, curve: middle) Draw.drawCircle(context, center: curve.point(at: 0.33), radius: 4) Draw.drawCircle(context, center: curve.point(at: 0.66), radius: 4) ``` ``` -------------------------------- ### Reducing Curves to Simple Segments Source: https://context7.com/hfutrell/bezierkit/llms.txt Decompose complex curves into simpler subcurves using `reduce()`. This is essential for reliable scaling and offsetting operations. ```swift import BezierKit let complex = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 300, y: 200), p2: CGPoint(x: -100, y: 200), p3: CGPoint(x: 200, y: 0) ) let simpleSegments: [Subcurve] = complex.reduce() print("Decomposed into \(simpleSegments.count) simple subcurve(s)") for s in simpleSegments { print(" t1=\(s.t1), t2=\(s.t2), simple=\(s.curve.simple)") } // Scale a simple segment by a fixed offset distance if let scaled = simpleSegments.first?.curve.scale(distance: 10) { print("Scaled first subcurve: \(scaled.points)") } ``` -------------------------------- ### Extrema Calculation Source: https://context7.com/hfutrell/bezierkit/llms.txt The `extrema()` method returns the t-values at which the curve reaches its x and y extrema. These values are crucial for precise bounding box calculations. ```APIDOC ## Extrema `extrema()` returns the t-values at which the curve reaches its x and y extrema, which are used internally to compute precise bounding boxes. ```swift import BezierKit let curve = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 200, y: 300), p2: CGPoint(x: -100, y: 200), p3: CGPoint(x: 100, y: 0) ) let extrema = curve.extrema() print("x extrema t-values: \(extrema.x)") // t-values for x-axis extrema print("y extrema t-values: \(extrema.y)") // t-values for y-axis extrema print("all extrema t-values: \(extrema.all)") // Get the actual points at those t-values let extremaPoints = extrema.all.map { curve.point(at: $0) } print("extrema points: \(extremaPoints)") ``` ``` -------------------------------- ### Reduce to Simple Subcurves Source: https://context7.com/hfutrell/bezierkit/llms.txt Decomposes a curve into an array of 'simple' `Subcurve` segments. This is a prerequisite for reliable scaling and offset operations. Each subcurve has control points on the same side of the baseline and an end-normal angle difference less than 60°. ```APIDOC ## reduce() ### Description Decomposes a curve into an array of "simple" `Subcurve` segments. ### Method `reduce() -> [Subcurve]` ## scale(distance:) ### Description Scales a simple segment by a fixed offset distance. ### Method `scale(distance: Double) -> Self?` ``` -------------------------------- ### Curve Intersection Source: https://context7.com/hfutrell/bezierkit/llms.txt Finds intersection points between two curves using `intersections(with:)`. It also provides `selfIntersections` for cubic curves and a boolean check `intersects(_:accuracy:)` for proximity. ```APIDOC ## Curve Intersection `intersections(with:)` finds all intersection points between two curves, returning `[Intersection]` objects containing the `t1` and `t2` parameter values at each crossing. Cubic curves may also self-intersect, detectable via `selfIntersections`. ```swift import BezierKit let curve1 = CubicCurve( p0: CGPoint(x: 0, y: 100), p1: CGPoint(x: 200, y: 300), p2: CGPoint(x: 200, y: -100), p3: CGPoint(x: 400, y: 100) ) let curve2 = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 200, y: 400), p2: CGPoint(x: 200, y: -200), p3: CGPoint(x: 400, y: 200) ) // Find all intersections between two curves let intersections: [Intersection] = curve1.intersections(with: curve2) let points: [CGPoint] = intersections.map { curve1.point(at: $0.t1) } print("Found \(intersections.count) intersection(s)") for i in intersections { print(" t1=\(i.t1), t2=\(i.t2), point=\(curve1.point(at: i.t1))") } // Check whether a curve self-intersects (only cubics can) let selfIntersectingCurve = CubicCurve( p0: CGPoint(x: 0, y: 0), p1: CGPoint(x: 200, y: 200), p2: CGPoint(x: 0, y: 200), p3: CGPoint(x: 200, y: 0) ) print("self-intersects: \(selfIntersectingCurve.selfIntersects)") let selfCrossings: [Intersection] = selfIntersectingCurve.selfIntersections print("self-intersection t-values: t1=\(selfCrossings.first?.t1 ?? -1), t2=\(selfCrossings.first?.t2 ?? -1)") // Quick boolean check let doesIntersect: Bool = curve1.intersects(curve2, accuracy: 0.5) ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.