Add new 'arcs' (extrapoloated) line join.
authortbah <tavmjong@free.fr>
Thu, 29 Nov 2012 20:06:19 +0100
changeset 403 34d365211ba7
parent 402 4ac1fd244337
child 404 fa94e3877b95
Add new 'arcs' (extrapoloated) line join.
master/images/painting/linejoin-construction-arcs.png
master/images/painting/linejoin-construction-arcs.svg
master/images/painting/linejoin-four.png
master/images/painting/linejoin-four.svg
master/painting.html
Binary file master/images/painting/linejoin-construction-arcs.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/images/painting/linejoin-construction-arcs.svg	Thu Nov 29 20:06:19 2012 +0100
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="200">
+  <defs>
+    <g id="dot">
+      <rect x="-3" y="-3" width="6" height="6" fill="white"/>
+      <rect x="-2" y="-2" width="4" height="4" fill="black"/>
+    </g>
+  </defs>
+  <g>
+    <!-- Dark gray stroke -->
+    <path
+       style="fill:none;stroke:#444;stroke-width:40"
+       d="m 286.4,79.3 c -14.2,24.8 -30.4,48.4 -47.4,71.11508 -6.0,7.8 -12.2,15.5 -18.6,23.0 M 89.8,116.8 c 67.0,1.9 134.1,-7.7 195.1,-36.9 0.47,-0.2 0.9,-0.4 1.4,-0.7" />
+    <!-- Light gray path -->
+    <path
+       d="m 286.4,79.3 c -14.2,24.8 -30.4,48.4 -47.4,71.11508 -6.0,7.8 -12.2,15.5 -18.6,23.0 M 89.8,116.8 c 67.0,1.9 134.1,-7.7 195.1,-36.9 0.47,-0.2 0.9,-0.4 1.4,-0.7"
+       style="fill:none;stroke:#ccc;stroke-width:2" />
+  </g>
+  <!-- Line join -->
+  <path
+      style="fill:deeppink"
+      d="m 277.5,61.6 8.5,17.5 17.7,10.2 c 7.8,-11.7 24.7,-49.2 29.9,-61.9 -19.8,14.2 -37.5,25.5 -56.1,34.2 z" />
+  <!-- Path circles -->
+  <g style="fill:none;stroke:black;stroke-dasharray:3,3"> 
+    <path
+	d="m 565,39 a 360,360 0 1 1 -720,0 360,360 0 1 1 720,0 z"
+        transform="translate(-73.9,-284.8)" />
+    <path
+	transform="translate(-355.4,-203.7)"
+	d="M 705,39 A 500,500 0 1 1 -295,39 500,500 0 1 1 705,39 z" />
+  </g>
+  <!-- Stroke edge circles -->
+  <g style="fill:none;stroke:#6a9100">
+    <path
+        d="M 725,39 A 520,520 0 1 1 -315,39 520,520 0 1 1 725,39 z"
+	transform="translate(-355.4,-203.7)" />
+    <path
+	transform="translate(-73.9,-284.8)"
+	d="m 545,39 a 340,340 0 1 1 -680,0 340,340 0 1 1 680,0 z" />
+  </g>
+  <use y="79" x="286" xlink:href="#dot" />
+  <use y="89" x="304" xlink:href="#dot" />
+  <use y="62" x="278" xlink:href="#dot" />
+  <use y="27" x="334" xlink:href="#dot" />
+  <!-- Text -->
+  <g style="font-size:12px;font-family:sans-serif">
+    <text style="text-anchor:middle;fill:#ccc" y="94" x="289">P</text>
+    <text style="text-anchor:end;fill:#444" y="61" x="272">P1</text>
+    <text style="fill:#444" y="103" x="304">P2</text>
+    <text style="text-anchor:middle;fill:#444" y="26" x="323">P4</text>
+    <text style="text-anchor:end" y="77" x="85">A<tspan style="font-size:10px" dy="2">outside</tspan></text>
+    <text style="text-anchor:end" y="186" x="295">B<tspan style="font-size:10px" dy="2">outside</tspan>
+    </text>
+  </g>
+</svg>
Binary file master/images/painting/linejoin-four.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/images/painting/linejoin-four.svg	Thu Nov 29 20:06:19 2012 +0100
@@ -0,0 +1,40 @@
+<?xml version="1.0" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+     width="800" height="180" viewBox="0 0 800 180">
+  <desc>Example linecap - demonstrates four stroke-linecap values</desc>
+  <style type="text/css"><![CDATA[
+    .thick { stroke: black; stroke-width: 35px }
+    .thin { stroke: #ccc; stroke-width: 2px }
+    text { text-anchor: middle; font: 16px sans-serif }
+    circle { fill: #ccc; stroke: none }
+  ]]></style>
+  <defs>
+    <path id="path1" d="m 25,130 c 0,-40 50,-75 100,-75 -35,20 -50,50 -50,75" fill="none" />
+    <circle id="circle1" cx="125" cy="55" r="4"/>
+  </defs>
+  <g transform="translate(0,0)">
+    <use class="thick" xlink:href="#path1" stroke-linejoin="miter"/>
+    <use class="thin" xlink:href="#path1"/>
+    <use xlink:href="#circle1"/>
+    <text x="100" y="160">‘miter’ join</text>
+  </g>
+  <g transform="translate(200,0)">
+    <use class="thick" xlink:href="#path1" stroke-linejoin="round"/>
+    <use class="thin" xlink:href="#path1"/>
+    <use xlink:href="#circle1"/>
+    <text x="100" y="160">‘round’ join</text>
+  </g>
+  <g transform="translate(400,0)">
+    <use class="thick" xlink:href="#path1" stroke-linejoin="bevel"/>
+    <use class="thin" xlink:href="#path1"/>
+    <use xlink:href="#circle1"/>
+    <text x="100" y="160">‘bevel’ join</text>
+  </g>
+  <path id="join" d="m 724,37.5 c 18,0 41,3.6 65,17.7 C 769,55.6 750,60.7 733,70.6 Z"/>
+  <g transform="translate(600,0)">
+    <use class="thick" xlink:href="#path1" stroke-linejoin="bevel"/>
+    <use class="thin" xlink:href="#path1"/>
+    <use xlink:href="#circle1"/>
+    <text x="100" y="160">‘arcs’ join</text>
+  </g>
+</svg>
--- a/master/painting.html	Thu Nov 29 15:08:21 2012 +1100
+++ b/master/painting.html	Thu Nov 29 20:06:19 2012 +0100
@@ -727,7 +727,7 @@
   </tr>
   <tr>
     <th>Value:</th>
-    <td>miter | round | bevel</td>
+    <td>miter | round | bevel | arcs </td>
   </tr>
   <tr>
     <th>Initial:</th>
@@ -776,12 +776,33 @@
   <dt><span class='prop-value'>bevel</span></dt>
   <dd>This value indicates that a bevelled corner is to be used to join path segments.
   The bevel shape is a triangle that fills the area between the two stroked segments.</dd>
+
+  <dt><span class='prop-value'>arcs</span></dt>
+  <dd>This value indicates that an arcs corner is to be used to join
+    path segments. The arcs shape is formed by extending the outer
+    edges of the stroke at the join point with arcs that have the same
+    curvature as the outer edges at the join point.</dd>
 </dl>
 
+<p class="issue">Is there a better name than <i>arcs</i> for this property value?
+I (Tav) prefer <i>talon</i> (as in bird claw). The term <i>arc</i> has other uses
+in SVG and in graphics in general. The term <i>talon</i> would be unique as well
+as fit in with the existing property value names for line-join.</p>
+
+<p class="issue">How does the miter limit apply? (It's hard to get really
+long joins.) Do you fall back to miter or bevel? (Probably miter as it is
+more in the style.)</p>
+
+<p class="note">The <span class='prop-value'>arcs</span> value is new in SVG 2.
+It was added to provide a better looking join when the path segments at the
+join are curved.</p>
+
+<p class="annotation">Adding new line join was approved at <a href="http://www.w3.org/2012/09/19-svg-minutes.html#item08">Rigi Kaltbad group meeting</a>.</p>
+
 <div class="figure">
-  <img class="bordered" src="images/painting/linejoin.svg"
-       alt="Image showing three paths, each with a different line join."/>
-  <p class="caption">The three types of line joins.</p>
+  <img class="bordered" src="images/painting/linejoin-four.svg"
+       alt="Image showing four paths, each with a different line join."/>
+  <p class="caption">The four types of line joins.</p>
 </div>
 
 <table class="propdef">
@@ -831,6 +852,8 @@
 length to the <a>'stroke-width'</a>. When the limit is exceeded, the
 join is converted from a miter to a bevel.</p>
 
+<p class="issue">How should this apply to arcs line-joins?</p>
+
 <dl>
   <dt><span class='prop-value'>&lt;number&gt;</span></dt>
   <dd>The limit on the ratio of the miter length to the <a>'stroke-width'</a>.
@@ -1275,6 +1298,23 @@
   <var>P</var><sub>1</sub> and <var>P</var><sub>2</sub> as the two endpoints of
   the arc.</li> 
 
+  <li>If <a>'stroke-linejoin'</a> is <span class="prop-value">arcs</span>,
+    then find the circles that are tangent to the stroke edges at
+    <var>P</var><sub>1</sub> and <var>P</var><sub>2</sub> with the
+    same curvature as the edges at those points (see below). If both
+    curvatures are zero fall through to <span class="prop-value">miter</span>.
+    Extend the stroke edges using these circles (or a line, in the case
+    of zero curvature). If the two circles (or circle and line)
+    intersect, return the area inside the region defined by the lines
+    that connect <var>P</var> with <var>P</var><sub>1</sub>
+    and <var>P</var><sub>2</sub> and the arcs defined by the circles
+    (or arc and line) between the closest intersection point
+    to <var>P</var>, and <var>P</var><sub>1</sub> and
+    <var>P</var><sub>2</sub>. If the two circles (or circle and line)
+    do not intersect, fall through to <span class="prop-value">miter</span>.
+    Note that the curvatures are calculated in user-space before any
+    transforms are applied.</li>
+
   <li>Let <var>θ</var> be the angle between <var>A</var> and <var>B</var>.</li>
 
   <li>If <a>'stroke-linejoin'</a> is <span class="prop-value">miter</span> and
@@ -1293,6 +1333,321 @@
   point, and the gray region is the stroke.</p>
 </div>
 
+<div class="figure">
+  <img class="bordered" src="images/painting/linejoin-construction-arcs.svg"
+       alt="Image showing the lines and points computed to construct an arcs line join."/>
+  <p class="caption">Construction of an arcs line join shape, shown in
+    pink. The white line is the original path, which has two segments
+    that come to a point, and the gray region is the stroke. The
+    dashed lines show circles that are tangent to and have the
+    curvature of the segments at the join.  The olive-green circles
+    (concentric with the dashed circles) define the join shape.</p>
+</div>
+
+<h3 id="CurvatureCalculation">Computing the circles for the <span class="prop-value">arcs</span>
+'stroke-linejoin'</h3>
+
+<p>The <span class="prop-value">arcs</span> <a>'stroke-linejoin'</a>
+  requires finding circles that are both tangent to and have the same
+  curvatures as the outer stroke edges at the ends of path
+  segments. To find one of these circles, first calculate the
+  curvature <var>&#x03BA;</var> of the path segment at its end (see
+  below). Next, find the radius of a circle corresponding to this
+  curvature: <var>r</var> = 1/<var>&#x03BA;</var>. Increase or
+  decrease the radius by one half of the stroke width to account for
+  the stroke: <var>r<sub>c</sub></var> = <var>r</var> &#x00b1; &#xbd;
+  stroke-width. The center of the circle will be on a line normal to
+  the path end a distance of <var>r<sub>c</sub></var> away from the
+  outer stroke edge at the end.</p>
+
+<p>For a line: the curvature is infinite. Extend the outer stroke edge by a line.</p>
+
+<p>For an elliptical arc:</p>
+<p class="issue">Need to do. This isn't as trivial as it first looks since we have to deal
+  with rx != ry and an arbitrary rotation.</p>
+
+<p>For a quadratic Bézier:
+
+  <div role="math" aria-describedby="math-quadratic-start">
+    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+      <mi>&#x03BA;<!-- κ --></mi>
+      <mo stretchy="false">(</mo>
+      <mn>0</mn>
+      <mo stretchy="false">)</mo>
+      <mo>=</mo>
+      <mrow class="MJX-TeXAtom-ORD">
+	<mfrac>
+	  <mn>1</mn>
+	  <mn>2</mn>
+	</mfrac>
+      </mrow>
+      <mrow class="MJX-TeXAtom-ORD">
+	<mfrac>
+	  <mrow>
+            <mo stretchy="false">(</mo>
+            <msub>
+              <mi>P</mi>
+              <mn>1</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>0</mn>
+            </msub>
+            <mo stretchy="false">)</mo>
+            <mo>&#x00D7;<!-- × --></mo>
+            <mo stretchy="false">(</mo>
+            <msub>
+              <mi>P</mi>
+              <mn>2</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>1</mn>
+            </msub>
+            <mo stretchy="false">)</mo>
+	  </mrow>
+	  <mrow>
+            <mrow class="MJX-TeXAtom-ORD">
+              <mo stretchy="false">|</mo>
+            </mrow>
+            <msub>
+              <mi>P</mi>
+              <mn>1</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>0</mn>
+            </msub>
+            <msup>
+              <mrow class="MJX-TeXAtom-ORD">
+		<mo stretchy="false">|</mo>
+              </mrow>
+              <mn>3</mn>
+            </msup>
+	  </mrow>
+	</mfrac>
+      </mrow>
+    </math>
+    <pre id="math-quadratic-start">$$\kappa(0) = {2\over3}{(P_1-P_0)\times((P_0-P_1)+(P_2-P_1))\over|P_1-P_0|^3}$$</pre>
+  </div>
+
+  <div role="math" aria-describedby="math-quadratic-end">
+    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+      <mi>&#x03BA;<!-- κ --></mi>
+      <mo stretchy="false">(</mo>
+      <mn>1</mn>
+      <mo stretchy="false">)</mo>
+      <mo>=</mo>
+      <mrow class="MJX-TeXAtom-ORD">
+	<mfrac>
+	  <mn>1</mn>
+	  <mn>2</mn>
+	</mfrac>
+      </mrow>
+      <mrow class="MJX-TeXAtom-ORD">
+	<mfrac>
+	  <mrow>
+            <mo stretchy="false">(</mo>
+            <msub>
+              <mi>P</mi>
+              <mn>2</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>1</mn>
+            </msub>
+            <mo stretchy="false">)</mo>
+            <mo>&#x00D7;<!-- × --></mo>
+            <mo stretchy="false">(</mo>
+            <msub>
+              <mi>P</mi>
+              <mn>0</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>1</mn>
+            </msub>
+            <mo stretchy="false">)</mo>
+	  </mrow>
+	  <mrow>
+            <mrow class="MJX-TeXAtom-ORD">
+              <mo stretchy="false">|</mo>
+            </mrow>
+            <msub>
+              <mi>P</mi>
+              <mn>2</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>1</mn>
+            </msub>
+            <msup>
+              <mrow class="MJX-TeXAtom-ORD">
+		<mo stretchy="false">|</mo>
+              </mrow>
+              <mn>3</mn>
+            </msup>
+	  </mrow>
+	</mfrac>
+      </mrow>
+    </math>
+    <pre id="math-quadratic-start">$$\kappa(0) = {2\over3}{(P_1-P_0)\times((P_0-P_1)+(P_2-P_1))\over|P_1-P_0|^3}$$</pre>
+  </div>
+
+  Where <var>&#x03BA;(0)</var> and <var>&#x03BA;(1)</var> are the
+  signed curvatures at the start and end of the path segment
+  respectively, and the <var>P</var>'s are the three points that
+  define the quadratic Bézier.</p>
+
+<p>For a cubic Bézier:
+
+  <div role="math" aria-describedby="math-cubic-start">
+    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+      <mi>&#x03BA;<!-- κ --></mi>
+      <mo stretchy="false">(</mo>
+      <mn>0</mn>
+      <mo stretchy="false">)</mo>
+      <mo>=</mo>
+      <mrow class="MJX-TeXAtom-ORD">
+	<mfrac>
+	  <mn>2</mn>
+	  <mn>3</mn>
+	</mfrac>
+      </mrow>
+      <mrow class="MJX-TeXAtom-ORD">
+	<mfrac>
+	  <mrow>
+            <mo stretchy="false">(</mo>
+            <msub>
+              <mi>P</mi>
+              <mn>1</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>0</mn>
+            </msub>
+            <mo stretchy="false">)</mo>
+            <mo>&#x00D7;<!-- × --></mo>
+            <mo stretchy="false">(</mo>
+            <msub>
+              <mi>P</mi>
+              <mn>2</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>1</mn>
+            </msub>
+            <mo stretchy="false">)</mo>
+	  </mrow>
+	  <mrow>
+            <mrow class="MJX-TeXAtom-ORD">
+              <mo stretchy="false">|</mo>
+            </mrow>
+            <msub>
+              <mi>P</mi>
+              <mn>1</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>0</mn>
+            </msub>
+            <msup>
+              <mrow class="MJX-TeXAtom-ORD">
+		<mo stretchy="false">|</mo>
+              </mrow>
+              <mn>3</mn>
+            </msup>
+	  </mrow>
+	</mfrac>
+      </mrow>
+    </math>
+    <pre id="math-cubic-start">$$\kappa(0) = {2\over3}{(P_1-P_0)\times((P_0-P_1)+(P_2-P_1))\over|P_1-P_0|^3}$$</pre>
+  </div>
+
+  <div role="math" aria-describedby="math-cubic-end">
+    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+      <mi>&#x03BA;<!-- κ --></mi>
+      <mo stretchy="false">(</mo>
+      <mn>1</mn>
+      <mo stretchy="false">)</mo>
+      <mo>=</mo>
+      <mrow class="MJX-TeXAtom-ORD">
+	<mfrac>
+	  <mn>2</mn>
+	  <mn>3</mn>
+	</mfrac>
+      </mrow>
+      <mrow class="MJX-TeXAtom-ORD">
+	<mfrac>
+	  <mrow>
+            <mo stretchy="false">(</mo>
+            <msub>
+              <mi>P</mi>
+              <mn>3</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>2</mn>
+            </msub>
+            <mo stretchy="false">)</mo>
+            <mo>&#x00D7;<!-- × --></mo>
+            <mo stretchy="false">(</mo>
+            <msub>
+              <mi>P</mi>
+              <mn>1</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>2</mn>
+            </msub>
+            <mo stretchy="false">)</mo>
+	  </mrow>
+	  <mrow>
+            <mrow class="MJX-TeXAtom-ORD">
+              <mo stretchy="false">|</mo>
+            </mrow>
+            <msub>
+              <mi>P</mi>
+              <mn>3</mn>
+            </msub>
+            <mo>&#x2212;<!-- − --></mo>
+            <msub>
+              <mi>P</mi>
+              <mn>2</mn>
+            </msub>
+            <msup>
+              <mrow class="MJX-TeXAtom-ORD">
+		<mo stretchy="false">|</mo>
+              </mrow>
+              <mn>3</mn>
+            </msup>
+	  </mrow>
+	</mfrac>
+      </mrow>
+    </math>
+    <pre id="math-cubic-end">$$\kappa(1) = {2\over3}{(P_3-P_2)\times((P_1-P_2)+(P_3-P_2))\over|P_3-P_2|^3}$$</pre>
+  </div>
+
+  Where <var>&#x03BA;(0)</var> and <var>&#x03BA;(1)</var> are the
+  signed curvatures at the start and end of the path segment
+  respectively, and the <var>P</var>'s are the four points that define
+  the cubic Bézier. Note, if
+  <var>P<sub>0</sub></var> and <var>P<sub>1</sub></var>, or
+  <var>P<sub>2</sub></var> and <var>P<sub>3</sub></var> are degenerate, the
+  curvature will be infinite and a line should be used in constructing the join.</p>
+
+
 <h2 id="VisibilityControl">Controlling visibility: the effect of the <span
 class="property">'display'</span> and <span class="property">'visibility'</span>
 properties</h2>