title: Two-color Path object
body: <p>The following image illustrates what I am trying to achieve:</p>
  <p><a href="https://i.stack.imgur.com/YJnnh.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/YJnnh.png" alt="" /></a></p>
  
  <p>Basically I want to create two <a href="https://docs.microsoft.com/en-us/dotnet/api/system.windows.shapes.path?redirectedfrom=MSDN&amp;view=netframework-4.8" rel="nofollow noreferrer"><code>Path</code></a> objects that &quot;touch&quot; each other (parallel paths). This is XAML used to generate this image:</p>
  <pre><code>&lt;StackPanel Orientation=&quot;Horizontal&quot;&gt;
      &lt;StackPanel.LayoutTransform&gt;
          &lt;ScaleTransform CenterX=&quot;0&quot; CenterY=&quot;0&quot; ScaleX=&quot;15&quot; ScaleY=&quot;15&quot; /&gt;
      &lt;/StackPanel.LayoutTransform&gt;
      
      &lt;Grid Margin=&quot;-5,0,0,0&quot;&gt;
          &lt;Path Stroke=&quot;Blue&quot;&gt;
              &lt;Path.Data&gt;
                  &lt;PathGeometry&gt;M10,10 C20,10 10,20 20,20&lt;/PathGeometry&gt;
              &lt;/Path.Data&gt;
          &lt;/Path&gt;
          &lt;Path Stroke=&quot;Red&quot;&gt;
              &lt;Path.Data&gt;
                  &lt;PathGeometry&gt;M10,11 C19,10.85 9,20.80 20,21&lt;/PathGeometry&gt;
              &lt;/Path.Data&gt;
          &lt;/Path&gt;
      &lt;/Grid&gt;
      
      &lt;Grid Margin=&quot;-5,0,0,0&quot;&gt;
          &lt;Path Stroke=&quot;Blue&quot;&gt;
              &lt;Path.Data&gt;
                  &lt;PathGeometry&gt;M10,10 C20,10 10,20 20,20&lt;/PathGeometry&gt;
              &lt;/Path.Data&gt;
          &lt;/Path&gt;
          &lt;Path Stroke=&quot;Red&quot;&gt;
              &lt;Path.Data&gt;
                  &lt;PathGeometry&gt;M10,11 C19,11 9,21 20,21&lt;/PathGeometry&gt;
              &lt;/Path.Data&gt;
          &lt;/Path&gt;
      &lt;/Grid&gt;
  &lt;/StackPanel&gt;
  </code></pre>
  <p>The first curve has hand-optimized point positions, the second has point positions easily calculated by taking stroke thickness into consideration. You can see the second curve is not perfect, because there is a space between the two. How can I create two perfectly &quot;touching&quot; curves programmatically, without hand-optimizing every curve (which is actually not possible because the curves are generated in code)?</p>
  <p>Simply put, I generate one curve (resp. <code>Path</code>) in code, and I need it to have two colors. So I thought making second parallel <code>Path</code> would do the trick, but adjusting <code>Geometry</code> of the second <code>Path</code> (to make it parallel) has proven to be problematic.</p>
  <h2>Update #1</h2>
  <p><a href="https://msdn.microsoft.com/magazine/msdn-magazine-issues#S5" rel="nofollow noreferrer">Parallel Lines and Curves</a> by <strong>Charles Petzold</strong> might be one way to solve this problem. It actually works pretty well, but it <em>flattens</em> the curves, which creates visual artifacts when deeply zoomed, and of course there is a performance drawback.</p>
  <blockquote>
  <p>The algorithm does not, however, attempt to find a Bézier curve that is parallel to another Bézier curve. The algorithm is instead based entirely on polylines: The input is one or more polylines and the output consists of multiple polylines for each input polyline. For this reason, ParallelPath needs to &quot;flatten&quot; the input geometry—which means converting the entire geometry (including arcs and Bézier curves) into a polyline approximation.</p>
  </blockquote>
  <h2>Update #2</h2>
  <p>So a friend of mine (math Ph.D. inceptor) has analyzed this problem and creating parallel curve to the (third-order) <a href="https://en.wikipedia.org/wiki/Bezier_curve" rel="nofollow noreferrer">Bézier curve</a> is very complex and computationally expensive. For each point of the parallel curve, computer would have to compute something like this:</p>
  <pre><code>(degree 3 polynomial) + (degree 2 polynomial) / sqrt(degree 4 polynomial)
  </code></pre>
  <p>Maybe there is a way to optimize this expression, but it would still be MUCH MORE computationally expensive than a standard Bézier curve (because the parallel curve is completely different curve than the original Bézier curve). I want to be able to animate the curve, so this solution would be probably too much CPU expensive. This leaves us with a couple of options:</p>
  <ol>
  <li><p>Use <strong>Charles Petzold</strong>'s polyline approximation, which works wonders, but there are visual glitches when deeply zoomed.</p>
  </li>
  <li><p>Derive our own approximation based on Charles Petzond's one. Use Bézier curves instead of lines (maybe arcs would be enough). This would solve the deep zoom problem, but it's probably quite hard to code (I have no clue how to do this).</p>
  </li>
  <li><p>Maybe it is possible to create something like two-color brush. This way, we could use just a single <code>Path</code> to achieve desired result (as shown by the first image). I haven't seen it anywhere though, so this is probably not an option.</p>
  </li>
  </ol>
  <h2>Update #3</h2>
  <p>I've found some pretty interesting links:</p>
  <ul>
  <li><a href="https://stackoverflow.com/questions/4148831/how-to-offset-a-cubic-bezier-curve">How to offset a cubic bezier curve?</a>  (<a href="https://stackoverflow.com/questions/4148831/how-to-offset-a-cubic-bezier-curve/4161777#4161777">Heuristic algorithm</a>)</li>
  <li><a href="https://stackoverflow.com/questions/408457/outline-of-cubic-bezier-curve-stroke">Outline of cubic bezier curve stroke</a></li>
  <li><a href="https://stackoverflow.com/questions/3205819/bezier-path-widening">bezier path widening</a> (<a href="https://stackoverflow.com/questions/3205819/bezier-path-widening/3220819#3220819">Python algorithm</a>)</li>
  <li><a href="https://seant23.wordpress.com/2010/11/12/offset-bezier-curves/" rel="nofollow noreferrer">Offset Bézier Curves</a> (<em>Java implementation of custom polyline Bézier curve approximation; implementation differs from the Charles Petzold's one</em>)</li>
  <li><a href="https://www.smarterdigitalmarketing.co.uk/glasgow/web-design/" rel="nofollow noreferrer">Parallel Bézier</a> (<em>Why parallel Bézier curves are not possible from math point of view</em>)</li>
  <li>Fast, precise flattening of cubic Bézier path and offset curves paper (<a href="https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.5344&amp;rep=rep1&amp;type=pdf" rel="nofollow noreferrer">Download link 1</a>,  <a href="https://www.southalabama.edu/colleges/soc/" rel="nofollow noreferrer">Download link 2</a>)</li>
  </ul>
  <p>More info:</p>
  <ul>
  <li>QPainterPathStroker from Qt framework is supposed to be using the Thomas F. Hain's algorithm for parallel curves</li>
  <li>This <a href="http://hg.openjdk.java.net/jdk7/2d-gate/jdk/file/065e6c5a8027/src/share/classes/sun/java2d/pisces/Stroker.java" rel="nofollow noreferrer">Java Stroker</a> is also supposed to be capable of drawing parallel curves</li>
  </ul>
  <p>Maybe the final solution? (source <a href="https://seant23.wordpress.com/2010/11/12/offset-bezier-curves/#comment-16" rel="nofollow noreferrer">here</a>)</p>
  <blockquote>
  <p>... I worked out all I knew about Bezier curve theory, and developed the unflattened offsetting to something that is correct, and (monster) documented that on <a href="https://pomax.github.io/bezierinfo/" rel="nofollow noreferrer">A primer on Bezier curves</a></p>
  </blockquote>
  <hr />
  <h2>Attempt #1</h2>
  <p><a href="https://stackoverflow.com/questions/5588077/two-color-path-object/5588307#5588307"><em>Make second path a bit wider, and slide it underneath the first path while using Z-Index.</em></a>
  <a href="http://i51.tinypic.com/2r5vwjk.png" rel="nofollow noreferrer">http://i51.tinypic.com/2r5vwjk.png</a></p>
  <p>This won't work, the <code>Geometry</code> must be transformed accordingly.</p>