Re: [svgwg] SVG marker orientation at a 180° U-turn not well defined

I have been experimenting with various algorithms to try and improve the direction calculations at these 180° turn sites.  I've come up with what I think is a reasonable solution that can be implemented in just a handful of lines of code.

---
**The algorithm**

If the incoming and outgoing vectors at a midpoint are anti-parallel, there will be two possible options for an average vector.  They are the two perpendiculars. To select between the two:

1. Let Va be a vector from the last marker location (last mid point or start point, whether displayed of not) to the current marker location.
2. Test against Va. Choose the potential marker direction that points in the same direction as Va. The vectors point in the same direction if the dot product is greater than zero.
3. If the dot product is zero (Va is perpendicular), then let Vb be a vector from the current marker location to the next marker location (next mid point or end point, whether displayed of not).
4. Test against Vb. Choose the potential marker direction that points in the same direction as Vb.
5. If that dot product is also zero (Vb is perpendicular), then choose the potential marker direction that has a positive X coordinate. If X is zero, then choose the direction that has a positive Y coordinate.
---

I've implemented this algorithm in my renderer. It added only about a dozen lines to my marker code.  Here's the result:

![improved_markers](https://user-images.githubusercontent.com/840288/28413865-3e564c30-6d9d-11e7-8a5a-88e94eb79b46.png)

It's not perfect, but I think it improves things a lot. There are are couple of what I consider "failures" there: the third one down in the second column, and the bottom one in the third column. 
 But fixing every scenario would add a lot more complexity to the algorithm.

Here's the test file if you want to see the difference on other browsers:

```
<svg xmlns="http://www.w3.org/2000/svg"
     viewBox="0 0 70 50"
     width="700" height="500">
  <marker id="m" overflow="visible" orient="auto">
    <polygon fill="red" fill-opacity="0.8" points="0,-1, 3,0, 0,1"/>
  </marker>
  <marker id="se" overflow="visible" orient="auto">
    <polygon fill="gold" fill-opacity="0.8" points="0,-1, 3,0, 0,1"/>
  </marker>
  <!-- ltr "bird" shape -->
  <path fill="none" stroke="navy"
        d="M 5 6 q 6 -3 6 3 q 0 -6 6 -3"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- ltr "inverted bird" shape -->
  <path fill="none" stroke="navy"
        d="M 5 18 q 6 3 6 -3 q 0 6 6 3"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- ltr "T" shape -->
  <path fill="none" stroke="navy"
        d="M 24 3 l 5 5 l -5 5 l 5 -5 l 5 5"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- ltr "M" shape -->
  <path fill="none" stroke="navy"
        d="M 24 21 c 0 -6 6 -6 6 0 c 0 -6 6 -6 6 0"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- ltr "claw" shape -->
  <path fill="none" stroke="navy"
        d="M 45 12 c 0 -3 6 -3 6 0 q 0 -6 -6 -6"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- ltr "claw" shape drawn top first -->
  <path fill="none" stroke="navy"
        d="M 45 15 q 6 0 6 6 c 0 -3 -6 -3 -6 0"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- ltr "slash" shape -->
  <path fill="none" stroke="navy"
        d="M 58 10 l 6 -6 l -6 6"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- ltr "backslash" shape -->
  <path fill="none" stroke="navy"
        d="M 58 14 l 6 6 l -6 -6"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- ltr horizontal line shape -->
  <path fill="none" stroke="navy"
        d="M 58 22 l 6 0 l -6 0"
        style="marker: url(#se); marker-mid: url(#m);" />

  <!-- rtl "bird" shape -->
  <path fill="none" stroke="seaGreen"
        d="M 17 28 q -6 -3 -6 3 q 0 -6 -6 -3"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- ltr "inverted bird" shape -->
  <path fill="none" stroke="seaGreen"
        d="M 17 40 q -6 3 -6 -3 q 0 6 -6 3"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- rtl "T" shape -->
  <path fill="none" stroke="seaGreen"
        d="M 36 35 l -5 -5 l -5 5 l 5 -5 l -5 -5"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- rtl "M" shape -->
  <path fill="none" stroke="seaGreen"
        d="M 36 43 c 0 -6 -6 -6 -6 0 c 0 -6 -6 -6 -6 0"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- rtl "claw" shape -->
  <path fill="none" stroke="seaGreen"
        d="M 51 34 c 0 -3 -6 -3 -6 0 q 0 -6 6 -6"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- rtl "claw" shape drawn top first -->
  <path fill="none" stroke="seaGreen"
        d="M 51 37 q -6 0 -6 6 c 0 -3 6 -3 6 0"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- rtl "slash" shape -->
  <path fill="none" stroke="seaGreen"
        d="M 64 32 l -6 -6 l 6 6"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- rtl "backslash" shape -->
  <path fill="none" stroke="seaGreen"
        d="M 64 36 l -6 6 l 6 -6"
        style="marker: url(#se); marker-mid: url(#m);" />
  <!-- rtl horizontal line shape -->
  <path fill="none" stroke="seaGreen"
        d="M 64 45 l -6 0 l 6 0"
        style="marker: url(#se); marker-mid: url(#m);" />
</svg>
```
https://jsfiddle.net/rchpq06L/6/

**Test file in Chrome**

![chrome](https://user-images.githubusercontent.com/840288/28413876-488c0988-6d9d-11e7-94d4-0aeb47e34823.png)

**Test file in Firefox**

![firefox](https://user-images.githubusercontent.com/840288/28413880-4b165956-6d9d-11e7-8cbf-462fa12d92b4.png)



-- 
GitHub Notification of comment by BigBadaboom
Please view or discuss this issue at https://github.com/w3c/svgwg/issues/333#issuecomment-316667975 using your GitHub account

Received on Thursday, 20 July 2017 10:50:57 UTC