module Graphics.Implicit.Export.Render.HandleSquares (mergedSquareTris) where
import Prelude(foldMap, (<>), ($), fmap, concat, (.), (==), compare, error)
import Graphics.Implicit.Definitions (TriangleMesh(TriangleMesh), Triangle(Triangle))
import Graphics.Implicit.Export.Render.Definitions (TriSquare(Tris, Sq))
import Data.VectorSpace ((^*), (*^), (^+^))
import GHC.Exts (groupWith)
import Data.List (sortBy)
mergedSquareTris :: [TriSquare] -> TriangleMesh
mergedSquareTris sqTris =
let
triTriangles :: [Triangle]
triTriangles = [tri | Tris tris <- sqTris, tri <- unmesh tris ]
squaresFromTris :: [TriSquare]
squaresFromTris = [ Sq x y z q | Sq x y z q <- sqTris ]
unmesh (TriangleMesh m) = m
planeAligned = groupWith (\(Sq basis z _ _) -> (basis,z)) squaresFromTris
joined = fmap
( concat . (fmap joinXaligned) . groupWith (\(Sq _ _ xS _) -> xS)
. concat . (fmap joinYaligned) . groupWith (\(Sq _ _ _ yS) -> yS)
. concat . (fmap joinXaligned) . groupWith (\(Sq _ _ xS _) -> xS))
planeAligned
finishedSquares = concat joined
in
TriangleMesh $ triTriangles <> foldMap squareToTri finishedSquares
joinXaligned :: [TriSquare] -> [TriSquare]
joinXaligned quads@((Sq b z xS _):_) =
let
orderedQuads = sortBy
(\(Sq _ _ _ (ya,_)) (Sq _ _ _ (yb,_)) -> compare ya yb)
quads
mergeAdjacent (pres@(Sq _ _ _ (y1a,y2a)) : next@(Sq _ _ _ (y1b,y2b)) : others) =
if y2a == y1b
then mergeAdjacent ((Sq b z xS (y1a,y2b)): others)
else if y1a == y2b
then mergeAdjacent ((Sq b z xS (y1b,y2a)): others)
else pres : mergeAdjacent (next : others)
mergeAdjacent a = a
in
mergeAdjacent orderedQuads
joinXaligned (Tris _:_) = error "Tried to join y aligned triangles."
joinXaligned [] = []
joinYaligned :: [TriSquare] -> [TriSquare]
joinYaligned quads@((Sq b z _ yS):_) =
let
orderedQuads = sortBy
(\(Sq _ _ (xa,_) _) (Sq _ _ (xb,_) _) -> compare xa xb)
quads
mergeAdjacent (pres@(Sq _ _ (x1a,x2a) _) : next@(Sq _ _ (x1b,x2b) _) : others) =
if x2a == x1b
then mergeAdjacent ((Sq b z (x1a,x2b) yS): others)
else if x1a == x2b
then mergeAdjacent ((Sq b z (x1b,x2a) yS): others)
else pres : mergeAdjacent (next : others)
mergeAdjacent a = a
in
mergeAdjacent orderedQuads
joinYaligned (Tris _:_) = error "Tried to join y aligned triangles."
joinYaligned [] = []
squareToTri :: TriSquare -> [Triangle]
squareToTri (Sq (b1,b2,b3) z (x1,x2) (y1,y2)) =
let
zV = b3 ^* z
(x1V, x2V) = (x1 *^ b1, x2 *^ b1)
(y1V, y2V) = (y1 *^ b2, y2 *^ b2)
a = zV ^+^ x1V ^+^ y1V
b = zV ^+^ x2V ^+^ y1V
c = zV ^+^ x1V ^+^ y2V
d = zV ^+^ x2V ^+^ y2V
in
[Triangle (a,b,c), Triangle (c,b,d)]
squareToTri (Tris t) = unmesh t
where
unmesh (TriangleMesh a) = a