module Graphics.Implicit.Export.MarchingSquaresFill (getContourMesh) where
import Graphics.Implicit.Definitions
import Control.Parallel (par, pseq)
getContourMesh :: ℝ2 -> ℝ2 -> ℝ2 -> Obj2 -> [(ℝ2,ℝ2,ℝ2)]
getContourMesh (x1, y1) (x2, y2) (dx, dy) obj =
let
nx = fromIntegral $ ceiling $ (x2 x1) / dx
ny = fromIntegral $ ceiling $ (y2 y1) / dy
trisOnGrid :: [[[(ℝ2,ℝ2,ℝ2)]]]
trisOnGrid = [[getSquareTriangles
(x1 + (x2 x1)*mx/nx, y1 + (y2 y1)*my/ny)
(x1 + (x2 x1)*(mx+1)/nx, y1 + (y2 y1)*(my+1)/ny)
obj
| mx <- [0.. nx1] ] | my <- [0..ny1] ]
triangles = concat $ concat trisOnGrid
in
triangles
getSquareTriangles :: ℝ2 -> ℝ2 -> Obj2 -> [(ℝ2,ℝ2,ℝ2)]
getSquareTriangles (x1, y1) (x2, y2) obj =
let
(x,y) = (x1, y1)
x1y1 = obj (x1, y1)
x2y1 = obj (x2, y1)
x1y2 = obj (x1, y2)
x2y2 = obj (x2, y2)
c = obj ((x1+x2)/2, (y1+y2)/2)
dx = x2 x1
dy = y2 y1
midx1 = (x, y + dy*x1y1/(x1y1x1y2))
midx2 = (x + dx, y + dy*x2y1/(x2y1x2y2))
midy1 = (x + dx*x1y1/(x1y1x2y1), y )
midy2 = (x + dx*x1y2/(x1y2x2y2), y + dy)
square a b c d = [(a,b,c), (a,c,d)]
in case (x1y2 <= 0, x2y2 <= 0,
x1y1 <= 0, x2y1 <= 0) of
(True, True,
True, True) -> square (x1,y1) (x2,y1) (x2,y2) (x1,y2)
(False, False,
False, False) -> []
(True, True,
False, False) -> square midx1 midx2 (x2,y2) (x1,y2)
(False, False,
True, True) -> square (x1,y1) (x2,y1) midx2 midx1
(False, True,
False, True) -> square midy1 (x2,y1) (x2,y2) midy2
(True, False,
True, False) -> square (x1,y1) midy1 midy2 (x1,y2)
(True, False,
False, False) -> [((x1,y2), midx1, midy2)]
(False, True,
True, True) ->
[(midx1, (x1,y1), midy2), ((x1,y1), (x2,y1), midy2), (midy2, (x2,y1), (x2,y2))]
(True, True,
False, True) ->
[((x1,y2), midx1, (x2,y2)), (midx1, midy1, (x2,y2)), ((x2,y2), midy1, (x2,y1))]
(False, False,
True, False) -> [(midx1, (x1,y1), midy1)]
(True, True,
True, False) ->
[(midy1,midx2,(x2,y2)), ((x2,y2), (x1,y2), midy1), (midy1, (x1,y2), (x1,y1))]
(False, False,
False, True) -> [(midx2, midy1, (x2,y1))]
(True, False,
True, True) ->
[(midy2, (x2,y1), midx2), ((x2,y1), midy2, (x1,y1)), ((x1,y1), midy2, (x1,y2))]
(False, True,
False, False) -> [(midx2, (x2,y2), midy2)]
(True, False,
False, True) -> if c > 0
then [((x1,y2), midx1, midy2), ((x2,y1), midy1, midx2)]
else []
(False, True,
True, False) -> if c <= 0
then []
else [((x1,y1), midy1, midx1), ((x2,y2), midx2, midy2)]