-- | Offsetting bezier curves and stroking curves. module Geom2D.CubicBezier.Outline (bezierOffset, bezierOffsetMax) where import Geom2D import Geom2D.CubicBezier.Basic import Geom2D.CubicBezier.Approximate import Geom2D.CubicBezier.Curvature offsetPoint :: Double -> Point -> Point -> Point offsetPoint dist start tangent = start ^+^ (rotate90L \$* dist *^ normVector tangent) bezierOffsetPoint :: CubicBezier -> Double -> Double -> (Point, Point) bezierOffsetPoint cb dist t = (offsetPoint dist p p', p') where (p, p') = evalBezierDeriv cb t -- Approximate the bezier curve offset by dist. A positive value -- means to the left, a negative to the right. offsetSegment :: Double -> Double -> CubicBezier -> [CubicBezier] offsetSegment dist tol cb = approximatePath (bezierOffsetPoint cb dist) 15 tol 0 1 offsetSegmentMax :: Int -> Double -> Double -> CubicBezier -> [CubicBezier] offsetSegmentMax m dist tol cb = approximatePathMax m (bezierOffsetPoint cb dist) 15 tol 0 1 -- | Calculate an offset path from the bezier curve to within -- tolerance. If the distance is positive offset to the left, -- otherwise to the right. A smaller tolerance may require more bezier -- curves in the path to approximate the offset curve bezierOffset :: CubicBezier -- ^ The curve -> Double -- ^ Offset distance. -> Double -- ^ Tolerance. -> [CubicBezier] -- ^ The offset curve bezierOffset cb dist tol = --Path \$ map BezierSegment \$ concatMap (offsetSegment dist tol) \$ splitBezierN cb \$ findRadius cb dist tol -- | Like bezierOffset, but limit the number of subpaths for each -- smooth subsegment. The number should not be smaller than one. bezierOffsetMax :: Int -> CubicBezier -> Double -> Double -> [CubicBezier] bezierOffsetMax n cb dist tol = -- Path \$ map BezierSegment \$ concatMap (offsetSegmentMax n dist tol) \$ splitBezierN cb \$ findRadius cb dist tol