question: contours and components inside some rect



  • Small scripting question. (Hopefully this heavy rain of the questions will end up at some point)

    What is the easiest way to check if some contour or component in the glyph is inside some abstract rectangle?

    I have coordinates and size of the rectangle. Now I would like to check out if the objects shapes are inside it.

    Determining if points are inside the rect is easy. But when it comes to components and contours: something that have lines and curves is really hard.
    I've been trying to creating the function, that would take the contour or component as an argument, and return True or False value. (True if at least part of the shape is inside the rectangle). I've been trying to do it with the booleanOperators and I failed.

    Any help?

    By the way, I'm thinking that it could be a bug:

    from mojo.tools import union
    g = CurrentGlyph()
    union(g, g[0], g[1], roundCoordinates=None)
    

    gives

    Traceback (most recent call last):
      File "<untitled>", line 3, in <module>
      File "/Applications/RoboFont3.app/Contents/Resources/lib/python3.6/mojo/tools.py", line 84, in union
      File "/Applications/RoboFont3.app/Contents/Resources/lib/python3.6/mojo/tools.py", line 84, in <listcomp>
      File "/Applications/RoboFont3.app/Contents/Resources/lib/python3.6/fontParts/base/base.py", line 255, in naked
      File "/Applications/RoboFont3.app/Contents/Resources/lib/python3.6/fontParts/base/base.py", line 232, in raiseNotImplementedError
    NotImplementedError: The RSegment subclass does not implement this method.
    

  • admin

    you can use the bounds of the contours or components to check if they overlap with the rectangle:

    def overlaps(contourOrComponent, box):
    
        left, bottom, right, top = contourOrComponent.bounds
        rectLeft, rectBottom, rectRight, rectTop = box
    
        xOverlap = right > rectLeft and left < rectRight
        yOverlap = top > rectBottom and bottom < rectTop
    
        if xOverlap and yOverlap:
            return True
        else:
            return False
    
    x, y, w, h = 118, 246, 104, 402
    box = x, y, x+w, y+h
    
    g = CurrentGlyph()
    
    for c in g.contours:
        print(overlaps(c, box), c)
    
    for c in g.components:
        print(overlaps(c, box), c)
    

  • admin

    regarding union: you need to use a glyph or a list of contours:

    from mojo.tools import union
    g = CurrentGlyph()
    union(g, [g[0]], [g[1]], roundCoordinates=None)
    

  • admin

    Two circular components could have overlapping bounds but have no visual overlap. The only option to check is to perform a remove overlap and look for changes. This means for components you have to decompose first.

    good luck!


  • admin

    @frederik true! but in this case we know that the frame is a rectangle – so checking the bounds works too. here’s a proof:

    overlap-proof.png

    g = CurrentGlyph()
    
    x, y, w, h = 206, -218, 358, 392
    box = x, y, x+w, y+h
    
    translate(230, 270)
    
    for contour in g.contours:
        color = (0, 1, 0) if overlaps(contour, box) else (1, 0, 0)
        fill(*color)
        B = BezierPath()
        contour.draw(B)
        drawPath(B)
    
    stroke(0)
    strokeWidth(10)
    fill(None)
    drawGlyph(g)
    
    stroke(0, 0, 1)
    rect(x, y, w, h)
    

  • admin

    oke, idd much simpler :)

    also take a look at fontTools arrayTools: sectRect, pointsInRect, pointInRect



  • Great! Thanks for the help!



  • @gferreira Hmm, I think it doesn't need to be true (Let's say that we have the shape of the glyph "C". The rect is inside of the letter: then it doesn't work)


  • admin

    @RafaŁ-Buchner you’re right :) better to use the boolean glyph method then.

    overlap-proof-failed.png



  • This post is deleted!