I would like to subtract one shape from another, and then combine the resulting shape with another shape. In my example a square is to be clipped in half and that clipped version is to be extended by a half circle to the right.
So I subtract one square from the other via difference
and make a union
with the whole circle assuming that overlapping areas will just merge.
I'm thinking in terms of set operations where ({1,2,3,4} / {3,4}) U {2,3}
equals {1,2,3}
but in my implementation it equals {1,3}
:
import Diagrams.Backend.SVG.CmdLine
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
import Diagrams.Prelude
import qualified Diagrams.TwoD.Path.Boolean as B
main = mainWith (combination # fc red # bgFrame 0.1 white)
where
combination :: QDiagram B V2 Double Any
combination = strokePath plusCircle
shorterSquare = B.difference Winding (square 2) (square 2 # translateX 1)
plusCircle = B.union Winding (circle 1 <> shorterSquare)
But I get this: This is not what I want, I want the half circle merged with the rectangle, and the result to be filled just red with no lines inside.
This particular usage of B.difference
reverses the direction of the shorterSquare
path, so you need to re-reverse it:
shorterSquare = B.difference Winding (square 2) (square 2 # translateX 1)
# reversePath
As this is quite subtle, it is worth it to spend a moment describing how I diagnosed it. Firstly, such fill rule wackiness felt quite like the sort of issue caused by path (or face, etc.) orientations. Secondly, redefining shorterSquare
as...
shorterSquare = square 2 # scaleX 0.5 # translateX 0.5
... gives the expected result. That means the issue has to do with B.difference
and the definition of shorterSquare
, rather than with B.union
. Confirmation can be obtained through pathVertices
:
GHCi> -- Counterclockwise.
GHCi> pathVertices $ square 2 # scaleX 0.5 # translateX 0.5
[[P (V2 1.0 (-1.0)),P (V2 0.9999999999999999 1.0),P (V2 (-1.1102230246251565e-16) 1.0),P (V2 (-2.220446049250313e-16) (-1.0))]]
GHCi> -- Clockwise.
GHCi> pathVertices $ B.difference Winding (square 2) (square 2 # translateX 1)
[[P (V2 (-1.0) 1.0),P (V2 0.0 1.0),P (V2 0.0 (-1.0)),P (V2 (-1.0) (-1.0))]]