haskellgraphicshaskell-diagrams

Diagrams boundingRect including the lines' width


Is there an equivalent to the boundingRect function which includes the diagram's lines width(*), so that each line, however thick it is, is entirely contained within the bounding rectangle? (the boundingRect function "ignores" their thickness and parts of the lines stay outside the bounding rectangle).

(*) My question is for lines with width expressed in local units.


Solution

  • Unfortunately there's no way to do this automatically yet. The easiest way would be to frame the diagram before finding the boundingRect. Since you're using the local units you just need to frame half the local width used in the diagram (add half of the line width used for the bounding rectangle if that has a line too).

    Here's a simple example:

    {-# LANGUAGE GADTs #-}
    
    import Diagrams.Prelude
    import Diagrams.Backend.Rasterific.CmdLine
    
    main :: IO ()
    main = mainWith $ frame 1 rects
    
    rects :: Diagram B
    rects = hsep 1 $ map (dia <>) [br1, br2, br3]
      where
        br1 = boundingRect dia # lwL 0.2 # lc red
        br2 = boundingRect (frame 0.1 dia) # fc dodgerblue # lw none
        br3 = boundingRect (frame 0.2 dia) # lwL 0.2 # lc red
    
    dia :: Diagram B
    dia = circle 3 # fc orange # lwL 0.2
    

    bounding rectangles

    A more general solution would be to draw the offset curves of each path using the local line width in the Diagram and find the bounding box of that. Diagrams.TwoD.Offset can almost do this but I don't think it works for all cases.