diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,12 @@
 # Revision history for juicy-gcode
 
+## 0.3.0.0 -- 2022-12-14
+
+- Add linear approximation algorithm
+- New option: --curve-fitting
+- Breaking change: --generate-bezier has been removed in favor of --curve-fitting
+- Breaking change: --resolution has been renamed to --tolerance
+
 ## 0.2.1.0 -- 2022-11-26
 
 - The approximation error is now calculated along the radial direction
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -5,7 +5,10 @@
 
 ## Overview
 
-Juicy-gcode is a configurable SVG to G-code converter that approximates bezier curves with [biarcs](http://dlacko.org/blog/2016/10/19/approximating-bezier-curves-by-biarcs/) for maximal curve fitting.
+Juicy-gcode is a configurable SVG to G-code converter that approximates bezier curves based on your needs:
+- with [biarcs](http://dlacko.org/blog/2016/10/19/approximating-bezier-curves-by-biarcs/) for maximal curve fitting: bezier curves are approximated with arcs ([G2, G3 commands](https://marlinfw.org/meta/gcode/)), the resulting path is [G1 continues](https://skill-lync.com/blogs/introductions-to-surface-continuities-and-its-types)
+- with linear approximation when arcs are not supported by your firmware: bezier curves are approximated with line segments ([G0, G1 commands](https://marlinfw.org/meta/gcode/)), the resulting path is [not smooth](https://skill-lync.com/blogs/introductions-to-surface-continuities-and-its-types), and the generated gcode is usually significantly larger 
+- with cubic bezier curves if your firmware supports it: some firmwares (e.g. [Marlin](https://marlinfw.org/docs/gcode/G005.html)) can handle bezier curves directly ([G5 command](https://marlinfw.org/meta/gcode/)), the result is [G2 continues](https://skill-lync.com/blogs/introductions-to-surface-continuities-and-its-types)
 
 ## Installation
 
@@ -20,9 +23,11 @@
 
 ## Usage
 
+> :warning: **Breaking change**: Since version 0.3.0.0, `--generate-bezier` has been removed in favor of the more generic `--curve-fitting` parameter and `--resolution` has been renamed to `--tolerance`
+
 > :warning: **Breaking change**: Since version 0.2.0.1, default DPI is changed to 96 and the option to mirror the Y axis is removed (it is always mirrored now for correct result)
 
-The easier way to use juicy-gcode is to simply provide an SVG file name. The generated GCode will be written to standard output.
+The easier way to use juicy-gcode is to simply provide an SVG file name. The generated GCode will be written to standard output. The default approximation method is the biarcs based.
 
 ```
 $ juicy-gcode SVGFILE
@@ -37,17 +42,22 @@
 Sometimes you want to overwrite some default settings. These are the 
 
 * *--dpi* (default 96 DPI) [the resolution of the SVG file](https://developer.mozilla.org/en-US/docs/Web/CSS/resolution) that is used to determine the size of the SVG when it does not contain explicit units
-* *--resolution* (default is 0.1 mm) the resolution of the generated GCode. Paths smaller than this are replaced by line segments instead of further approximated by biarcs
+* *--tolerance* (default is 0.1 mm) maximum allowed derivation of the approximation curve
  
 ```
-$ juicy-gcode SVGFILE --dpi 72 --resolution 0.01 
+$ juicy-gcode SVGFILE --dpi 72 --tolerance 0.01 
 ```
 
-Some firmwares (e.g. [Marlin](https://marlinfw.org/docs/gcode/G005.html)) can handle bezier curves directly. In this case
-you can command juicy-gcode not to approximate bezier-curves but emit them unchanged. 
+Curve fitting options (default is `biarc`):
 
 ```
-$ juicy-gcode SVGFILE --generate-bezier
+$ juicy-gcode SVGFILE --curve-fitting=biarc
+```
+```
+$ juicy-gcode SVGFILE --curve-fitting=linear
+```
+```
+$ juicy-gcode SVGFILE --curve-fitting=cubic-bezier
 ```
 
 ## Configuration
diff --git a/juicy-gcode.cabal b/juicy-gcode.cabal
--- a/juicy-gcode.cabal
+++ b/juicy-gcode.cabal
@@ -1,5 +1,5 @@
 name:                juicy-gcode
-version:             0.2.1.0
+version:             0.3.0.0
 license:             BSD3
 license-file:        LICENSE
 author:              dlacko
@@ -20,6 +20,7 @@
   main-is:                  Main.hs
 
   other-modules:            Approx.BiArc
+                            Approx.Linear
                             Graphics.BiArc
                             Graphics.CircularArc 
                             Graphics.CubicBezier
diff --git a/src/Approx/BiArc.hs b/src/Approx/BiArc.hs
--- a/src/Approx/BiArc.hs
+++ b/src/Approx/BiArc.hs
@@ -23,6 +23,7 @@
 maxiter = 10
 
 -- Approximate a bezier curve with biarcs (Left) and line segments (Right)
+-- M.A. Sabin, The use of piecewise forms for the numerical representation of shape (1977)
 bezier2biarcs :: B.CubicBezier
               -> Double
               -> [PathCommand]
@@ -33,10 +34,10 @@
         = [LineTo (toPoint (B._p2 mbezier))]
     -- Degenerate curve: p1 == c1, don't split
     | B._p1 mbezier == B._c1 mbezier
-        = approxOne mbezier
+        = approxSpiral mbezier
     -- Degenerate curve: p2 == c2, don't split
     | B._p2 mbezier == B._c2 mbezier
-        = approxOne mbezier
+        = approxSpiral mbezier
     -- Split by the inflexion points (if any)
     | otherwise
         = byInflection (B.inflectionPoints mbezier)
@@ -44,11 +45,11 @@
         order a b | b < a = (b, a)
                   | otherwise = (a, b)
 
-        byInflection [t] = approxOne b1 ++ approxOne b2
+        byInflection [t] = approxSpiral b1 ++ approxSpiral b2
             where
                 (b1, b2) = B.splitAt mbezier t
 
-        byInflection [t1, t2] = approxOne b1 ++ approxOne b2 ++ approxOne b3
+        byInflection [t1, t2] = approxSpiral b1 ++ approxSpiral b2 ++ approxSpiral b3
             where
                 (it1, it2') = order t1 t2
 
@@ -59,11 +60,11 @@
                 (b1, toSplit) = B.splitAt mbezier it1
                 (b2, b3) = B.splitAt toSplit it2
 
-        byInflection _ = approxOne mbezier
+        byInflection _ = approxSpiral mbezier
 
-        -- Recursive step (TODO: tail recursive) 
-        approxOne :: B.CubicBezier -> [PathCommand]
-        approxOne bezier
+        -- Apprixmate one bezier spiral
+        approxSpiral :: B.CubicBezier -> [PathCommand]
+        approxSpiral bezier
             -- Approximate bezier length. if max length is smaller than resolution, do not approximate
             | B.maxArcLength bezier < resolution
                 = [LineTo (toPoint (B._p2 bezier))]
@@ -110,7 +111,7 @@
                 (maxDistanceAt, maxDistance) = calculateMaxDistance bezier biarc
 
                 splitAndRecur t = let (b1, b2) = B.splitAt bezier t
-                                   in approxOne b1 ++ approxOne b2
+                                   in approxSpiral b1 ++ approxSpiral b2
 
 biarc2path :: BA.BiArc -> [PathCommand]
 biarc2path biarc = map
@@ -125,7 +126,7 @@
            CA._r (BA._a2 biarc) > 99999 || CA._r (BA._a2 biarc) < 0.001)
 
 -- Calculate the maximum approximation error along the radial direction
--- D.J. Walton*, D.S. Meek, Approximation of a planar cubic Bezier spiral by circular arcs (1996)
+-- D.J. Walton, D.S. Meek, Approximation of a planar cubic Bezier spiral by circular arcs (1996)
 calculateMaxDistance :: B.CubicBezier -> BA.BiArc -> (Double, Double)
 calculateMaxDistance bezier biarc
     -- This should not happenm but if, split the bezier at the middle
diff --git a/src/Approx/Linear.hs b/src/Approx/Linear.hs
new file mode 100644
--- /dev/null
+++ b/src/Approx/Linear.hs
@@ -0,0 +1,42 @@
+module Approx.Linear (
+    linearApprox
+) where
+
+import qualified Graphics.CubicBezier as B
+import qualified Graphics.Line as L
+import Graphics.Path
+import Graphics.Point
+
+import Linear.Metric
+
+-- Approximate a bezier curve with a series of points (line segments)
+-- Weiyin Ma, Renjiang Zhang, Efficient Piecewise Linear Approximation of Bézier Curves with Improved Sharp Error Bound (2006)
+linearApprox :: B.CubicBezier
+             -> Double
+             -> [PathCommand]
+linearApprox mbezier resolution
+    -- Edge case: all points on the same line -> it is a line 
+    | L.isOnLine (L.fromPoints (B._p2 mbezier) (B._p1 mbezier)) (B._c1 mbezier) &&
+      L.isOnLine (L.fromPoints (B._p2 mbezier) (B._p1 mbezier)) (B._c2 mbezier)
+        = [LineTo (toPoint (B._p2 mbezier))]
+    -- Just a regular bezier
+    | otherwise
+        = approx mbezier
+    where
+        approx :: B.CubicBezier -> [PathCommand]
+        approx bezier
+            | maxError > resolution
+                = splitAndRecur 0.5
+            | otherwise
+                = [LineTo (toPoint b1), LineTo (toPoint b2), LineTo (toPoint b3)]
+
+            where
+                b1 = ((9 * B._p1 bezier) + (15 * B._c1 bezier) + (7 * B._c2 bezier) + B._p2 bezier) / 32
+                b2 = (B._p1 bezier + (7 * B._c1 bezier) + (15 * B._c2 bezier) + (9 * B._p2 bezier)) / 32
+                b3 = B._p2 bezier
+
+                maxError = max (norm (B._p1 bezier - 2 * B._c1 bezier + B._c2 bezier))
+                               (norm (B._c1 bezier - 2 * B._c2 bezier + B._p2 bezier))
+
+                splitAndRecur t = let (nb1, nb2) = B.splitAt bezier t
+                                   in approx nb1 ++ approx nb2
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -14,13 +14,14 @@
 
 import Render
 import GCode
+import Data.Maybe (fromMaybe)
 
 data Options = Options { _svgfile        :: String
                        , _cfgfile        :: Maybe String
                        , _outfile        :: Maybe String
                        , _dpi            :: Int
                        , _resolution     :: Double
-                       , _generateBezier :: Bool
+                       , _approximation  :: Maybe Approximation
                        }
 
 options :: Parser Options
@@ -45,23 +46,31 @@
      <> metavar "DPI"
      <> help "Used to determine the size of the SVG when it does not contain any units; dot per inch (default is 96)" )
  <*> option auto
-      ( long "resolution"
+      ( long "tolerance"
      <> value 0.1
-     <> short 'r'
-     <> metavar "RESOLUTION"
-     <> help "Shorter paths are replaced by line segments; mm (default is 0.1)" )
-  <*> switch
-      ( long "generate-bezier"
-      <> short 'b'
-      <> help "Generate bezier curves (G5) instead of arcs (G2,G3)" )
+     <> short 't'
+     <> metavar "TOLERANCE"
+     <> help "Maximum derivation of the approximation curve" )
+  <*> optional (option parseApproximation
+      ( long "curve-fitting"
+      <> short 'c'
+      <> metavar "TYPE"
+      <> help "Bezier curve approximation algorithm. TYPE can be linear, biarc (default) or cubic-bezier" ))
 
+parseApproximation :: ReadM Approximation
+parseApproximation = str >>= \s -> case s of
+      "biarc"        -> return BiArc
+      "linear"       -> return Linear
+      "cubic-bezier" -> return CubicBezier
+      _ -> readerError "Accepted bezier approximation types are 'biarc', 'linear', and 'cubic-bezier'."
+
 runWithOptions :: Options -> IO ()
-runWithOptions (Options svgFile mbCfg mbOut dpi resolution generateBezier) =
+runWithOptions (Options svgFile mbCfg mbOut dpi resolution mbApproximation) =
     do
         mbDoc <- SVG.loadSvgFile svgFile
         flavor <- maybe (return defaultFlavor) readFlavor mbCfg
         case mbDoc of
-            (Just doc) -> writer (toString flavor dpi $ renderDoc generateBezier dpi resolution doc)
+            (Just doc) -> writer (toString flavor dpi $ renderDoc (fromMaybe BiArc mbApproximation) dpi resolution doc)
             Nothing    -> putStrLn "juicy-gcode: error during opening the SVG file"
     where
         writer = maybe putStr writeFile mbOut
diff --git a/src/Render.hs b/src/Render.hs
--- a/src/Render.hs
+++ b/src/Render.hs
@@ -1,4 +1,5 @@
 module Render (
+    Approximation(..),
     renderDoc
 ) where
 
@@ -12,6 +13,7 @@
 import Graphics.Point
 import Graphics.Transformation
 import Approx.BiArc
+import Approx.Linear
 import SvgArcSegment
 import SVGExt
 
@@ -82,8 +84,10 @@
 
         (w, h) = documentSize dpi doc
 
-renderDoc :: Bool -> Int -> Double -> SVG.Document -> [PathCommand]
-renderDoc generateBezier dpi resolution doc
+data Approximation = BiArc | CubicBezier | Linear
+
+renderDoc :: Approximation -> Int -> Double -> SVG.Document -> [PathCommand]
+renderDoc approximation dpi resolution doc
     = stage2 $ renderTrees (docTransform dpi doc) (SVG._elements doc)
     where
         pxresolution = fromIntegral dpi / 2.45 / 10 * resolution
@@ -96,13 +100,15 @@
                 approximate (MoveTo p:ds) _ = MoveTo p : approximate ds (fromPoint p)
                 approximate (LineTo p:ds) _ = LineTo p : approximate ds (fromPoint p)
                 approximate (ArcTo p1 p2 d:ds) _ = ArcTo p1 p2 d : approximate ds (fromPoint p2)
-                approximate (BezierTo c1 c2 p2:ds) cp
-                    | generateBezier
-                        = BezierTo c1 c2 p2 : approximate ds (fromPoint p2)
-                    | otherwise
-                        = bezier2biarcs
-                                    (B.CubicBezier cp (fromPoint c1) (fromPoint c2) (fromPoint p2)) pxresolution
-                                ++ approximate ds (fromPoint p2)
+                approximate (BezierTo c1 c2 p2:ds) cp =
+                    case approximation of
+                        BiArc       -> bezier2biarcs
+                                                (B.CubicBezier cp (fromPoint c1) (fromPoint c2) (fromPoint p2)) pxresolution
+                                            ++ approximate ds (fromPoint p2)
+                        CubicBezier -> BezierTo c1 c2 p2 : approximate ds (fromPoint p2)
+                        Linear      -> linearApprox
+                                                (B.CubicBezier cp (fromPoint c1) (fromPoint c2) (fromPoint p2)) pxresolution
+                                            ++ approximate ds (fromPoint p2)
 
         renderPathCommands :: Point -> Point -> Maybe Point -> [SVG.PathCommand] -> [PathCommand]
         renderPathCommands _ currentp _ (SVG.MoveTo origin (p:ps):ds)
