typesupply / lasermeasure

A laser measure tool.
MIT License
9 stars 1 forks source link

Stem measurement problem. #15

Closed typesupply closed 2 years ago

typesupply commented 2 years ago

Narrow shapes are problematic in the point-to-point algorithm. The algorithm is in the NearestPointsPointPen.find method. The algorithm is trying to find if the user has is using the current mouse location, location, (in glyph units) to see the distance between two on curve points.

The algorithm works by gathering all on curve points and then trying all combinations of point1 and point2. There are some optimizations at the start to eliminate obviously incorrect combinations, but after that the algorithm is basically this:

  1. Is the testing location roughly in the middle of the two points?
  2. Is the combination of (point1, location, point2) roughly collinear?
  3. Is the line between point1 and point2 close to a right angle?
  4. Does a line drawn between point1 and point2 intersect the glyph in more locations than just point1 and point2?

In narrow shapes, step 1 and step 2 create a situation in which the "middle" between points diagonally opposite each other is so large that it's counter-intuitive for the user. For example:

image

I haven't found a solution to eliminate this yet.


I think the same steps are causing nonsensical combinations to be considered correct. For example:

image

GLIF for testing:

<?xml version='1.0' encoding='UTF-8'?>
<glyph name="I" format="2">
  <advance width="509"/>
  <unicode hex="0049"/>
  <outline>
    <contour>
      <point x="130" y="665" type="line"/>
      <point x="130" y="85" type="line"/>
      <point x="100" y="0" type="line"/>
      <point x="250" y="0" type="line"/>
      <point x="220" y="85" type="line"/>
      <point x="220" y="665" type="line"/>
      <point x="250" y="750" type="line"/>
      <point x="100" y="750" type="line"/>
    </contour>
    <contour>
      <point x="319.0" y="0.0" type="line"/>
      <point x="409.0" y="0.0" type="line"/>
      <point x="409.0" y="750.0" type="line"/>
      <point x="319.0" y="750.0" type="line"/>
    </contour>
  </outline>
</glyph>
typesupply commented 2 years ago

@letterror and @typemytype, do you have any ideas?

jenskutilek commented 2 years ago

It looks like you are basically doing the same as an autohinter ;)

I have a script which does something similar, finding points that constitute stems to use for autohinting or for determining postscriptStemSnapH/postscriptStemSnapV.

Bildschirmfoto 2022-04-07 um 10 16 43

The analysing of outlines is done in a pen: StemPen.py.zip

At a quick glance, what I do that you don't is that the direction of outlines is taken into account.

For finding related points, the script checks if the directions are "paired", i.e. the outline direction is up in the first point and down in the second point, or, for vertical relations, if the outline directions are left to right and right to left through the respective point candidates.

That should avoid points on the same side of a "stem" being recognized as related.

typesupply commented 2 years ago

@jenskutilek Thanks! I do something similar in Glyph Nanny. Hm, I'll give it a try for this.


I added an experiment script that runs in the DrawBot extension in RoboFont. I has the point to point code isolated and it generates a visual report after testing manyManyManyManyManyManyManyManyManyMany locations to see what the nearest points are.

typesupply commented 2 years ago

The latest optimization seems to have broken some situations. Hovering in the middle of this glyph does not snap to the top/bottom points for some reason.

<?xml version='1.0' encoding='UTF-8'?>
<glyph name="zero.num" format="2">
  <advance width="242"/>
  <outline>
    <contour>
      <point x="121" y="706" type="curve"/>
      <point x="68" y="706"/>
      <point x="28" y="659"/>
      <point x="28" y="573" type="curve" smooth="yes"/>
      <point x="28" y="476" type="line" smooth="yes"/>
      <point x="28" y="389"/>
      <point x="68" y="343"/>
      <point x="121" y="343" type="curve"/>
      <point x="174" y="343"/>
      <point x="214" y="389"/>
      <point x="214" y="476" type="curve" smooth="yes"/>
      <point x="214" y="573" type="line" smooth="yes"/>
      <point x="214" y="659"/>
      <point x="174" y="706"/>
    </contour>
    <contour>
      <point x="121" y="689" type="curve"/>
      <point x="164" y="689"/>
      <point x="195" y="650"/>
      <point x="195" y="573" type="curve" smooth="yes"/>
      <point x="195" y="476" type="line" smooth="yes"/>
      <point x="195" y="399"/>
      <point x="164" y="360"/>
      <point x="121" y="360" type="curve"/>
      <point x="78" y="360"/>
      <point x="47" y="399"/>
      <point x="47" y="476" type="curve" smooth="yes"/>
      <point x="47" y="573" type="line" smooth="yes"/>
      <point x="47" y="650"/>
      <point x="78" y="689"/>
    </contour>
  </outline>
</glyph>