hasOverlap() does not detect all overlaps?



  • Hello,

    I'm currently working on a little tool and one of its functions is to detect and beyond that eventually remove overlaps.

    I am there fore using the hasOverlap() method like this:

    if glyph.hasOverlap():
        print(glyph.name)
        glyph.markColor = 0.5, 0, 0.2, 0.75
        # and so on
    

    This works quite reliable, with the exception, that it does not find the overlap in my /Y (my function to remove overlaps does not work either here since its depending on the outcome of the hasOverlap() function).

    The built-in right-click context function to remove overlaps works however.

    After some testing I found out, that it might be connected to the positioning of my outlines and points. As you can see the stem goes directly through the two points here.

    Bildschirmfoto 2019-04-29 um 13.21.03.png

    If the outline is just moved by one unit and the outline does not go directly through both points the overlap is detected.
    Am I missing something here, or is there another (or better) way to detect overlaps and to make my tool work?

    TIA
    daniel


  • admin

    hi @daniel,

    I can confirm the false negative for this particular shape. it looks like you’ve found a bug in the overlap detection algorithm 🐞 thanks!

    I’ll make a few more tests and create an issue in booleanOperations.



  • Ah, but since the built-in remove overlap in RF works in this case could you explain how this function detects the overlap and removes it?


  • admin

    can you share the glif xml of that Y? (copy paste the selection from RoboFont into the forum)



  • <?xml version='1.0' encoding='UTF-8'?>
    <glyph name="Y" format="2">
      <advance width="600"/>
      <unicode hex="0059"/>
      <outline>
        <contour>
          <point x="35" y="700" type="line"/>
          <point x="254" y="286" type="line"/>
          <point x="346" y="286" type="line"/>
          <point x="565" y="700" type="line"/>
          <point x="471" y="700" type="line"/>
          <point x="300" y="374" type="line"/>
          <point x="129" y="700" type="line"/>
        </contour>
        <contour>
          <point x="254" y="351" type="line"/>
          <point x="254" y="0" type="line"/>
          <point x="346" y="0" type="line"/>
          <point x="346" y="351" type="line"/>
        </contour>
      </outline>
    </glyph>
    

  • admin

    I think the problem can be generalized to colinear straight segments in different contours. here’s the bug report with a few more examples.

    you can ‘cheat’ the bug by moving the angled segments a few units down and inward:

    Screen Shot 2019-04-29 at 14.13.11.png



  • Exactly, moving the outline was my workaround as well.

    I'll keep an eye on the bug report too. Thanks for finding the additional cases where overlaps are not detected, this is quite helpful during the mastering process :)



  • Another reliable way to find overlaps could be this

    f = CurrentFont()
    
    for g in f:
        testglyph = g.copy()
        testglyph.removeOverlap()
        
        if len(g) != len(testglyph):
            g.mark = (0.5, 0, 0, 0.9)
    

    (idea of @benedikt)

    So far I had no complications with that method


  • admin

    in future version of RoboFont glyph.hasOverlaps() does not return a list of intersection anymore.

    It will return a boolean indicating if the glyph has overlaps. The check happens in similar way as your proposal. Only a bit faster :), as a booleanOperations.union takes a pointPen as argument, so you dont need to copy the whole glyph...



  • Cool :)

    It's already kind of not too slowly but you have to combine the above + hasOverlap() method to find everything.

    But less code and faster is always better :)