153 lines
4.2 KiB
Haskell
153 lines
4.2 KiB
Haskell
module Polyhedra
|
|
( translateXY
|
|
, rotateXY
|
|
, polyToEdges
|
|
, constructEdgesList
|
|
, boxXYZ
|
|
, boxABC
|
|
, boxXYZnobase
|
|
, polyToGeoRender
|
|
, polysToPic
|
|
)
|
|
where
|
|
import Geometry
|
|
--import Geometry.Data
|
|
import Geometry.Vector3D
|
|
import Polyhedra.Data
|
|
import Picture.Data
|
|
import Picture
|
|
|
|
import Data.Maybe
|
|
import Data.List
|
|
import Data.Bifunctor
|
|
import Control.Lens
|
|
--import qualified Data.Vector.Fusion.Stream.Monadic as VS
|
|
|
|
translateXY :: Float -> Float -> Polyhedra -> Polyhedra
|
|
translateXY x y = pyFaces %~ map (map $ first tran)
|
|
where
|
|
tran (V3 a b c) = V3 (a+x) (b+y) c
|
|
|
|
rotateXY :: Float -> Polyhedra -> Polyhedra
|
|
rotateXY a = over pyFaces $ map $ map $ first $ rotate3 a
|
|
|
|
-- Another representation of polyhedra is as a list of edges.
|
|
-- Each edge is a tuple containing four points: the first two are the two edge
|
|
-- coordinates, the last two being the normals of two planes of the polyhedra
|
|
-- that the edge connects.
|
|
--, _pyEdges :: [(Point3,Point3,Point3,Point3)]
|
|
|
|
constructEdges :: [[Point3]] -> [(Point3,Point3,Point3,Point3)]
|
|
constructEdges (face:faces) = mapMaybe (findReverseEdge otherEdges) (faceEdges face)
|
|
++ constructEdges faces
|
|
where
|
|
otherEdges = concatMap faceEdges faces
|
|
constructEdges _ = []
|
|
|
|
-- | a version of construct edges that directly returns the flattened list of
|
|
-- tuples
|
|
constructEdgesList :: [[Point3]] -> [Point3]
|
|
constructEdgesList (face:faces) = concatMap (findReverseEdgeList otherEdges) (faceEdges face)
|
|
++ constructEdgesList faces
|
|
where
|
|
otherEdges = concatMap faceEdges faces
|
|
constructEdgesList _ = []
|
|
|
|
|
|
findReverseEdge
|
|
:: [(Point3,Point3,Point3)]
|
|
-> (Point3,Point3,Point3)
|
|
-> Maybe (Point3,Point3,Point3,Point3)
|
|
findReverseEdge otherEdges (x,y,z) = (\(_,_,n) -> (x,y,z,n))
|
|
<$> find (\(a,b,_) -> (x,y) == (b,a)) otherEdges
|
|
|
|
findReverseEdgeList
|
|
:: [(Point3,Point3,Point3)]
|
|
-> (Point3,Point3,Point3)
|
|
-> [Point3]
|
|
findReverseEdgeList a b = case findReverseEdge a b of
|
|
Nothing -> []
|
|
Just (x,y,z,w) -> [x,y,z,w]
|
|
|
|
faceEdges :: [Point3] -> [(Point3,Point3,Point3)]
|
|
faceEdges xs = zipWith addNormal xs (tail xs ++ [head xs])
|
|
where
|
|
addNormal x y = (x,y,n)
|
|
(a:b:c:_) = xs
|
|
n = crossProd (b -.-.- a) (c -.-.- a)
|
|
|
|
rhombus :: Point3 -> Point3 -> [Point3]
|
|
{-# INLINE rhombus #-}
|
|
rhombus a b =
|
|
[V3 0 0 0
|
|
,a
|
|
,a +.+.+ b
|
|
,b
|
|
]
|
|
boxXYZnobase :: Float -> Float -> Float -> [[Point3]]
|
|
{-# INLINE boxXYZnobase #-}
|
|
boxXYZnobase x y z =
|
|
[ map (+.+.+ V3 0 0 z) $ reverse bottomFace
|
|
, frontFace
|
|
, map (+.+.+ V3 0 y 0) $ reverse frontFace
|
|
, sideFace
|
|
, map (+.+.+ V3 x 0 0) $ reverse sideFace
|
|
]
|
|
where
|
|
bottomFace = rhombus (V3 0 y 0) (V3 x 0 0)
|
|
frontFace = rhombus (V3 x 0 0) (V3 0 0 z)
|
|
sideFace = rhombus (V3 0 0 z) (V3 0 y 0)
|
|
|
|
boxXYZ :: Float -> Float -> Float -> [[Point3]]
|
|
{-# INLINE boxXYZ #-}
|
|
boxXYZ x y z =
|
|
[ bottomFace
|
|
, map (+.+.+ V3 0 0 z) $ reverse bottomFace
|
|
, frontFace
|
|
, map (+.+.+ V3 0 y 0) $ reverse frontFace
|
|
, sideFace
|
|
, map (+.+.+ V3 x 0 0) $ reverse sideFace
|
|
]
|
|
where
|
|
bottomFace = rhombus (V3 0 y 0) (V3 x 0 0)
|
|
frontFace = rhombus (V3 x 0 0) (V3 0 0 z)
|
|
sideFace = rhombus (V3 0 0 z) (V3 0 y 0)
|
|
boxABC :: Point3 -> Point3 -> Point3 -> [[Point3]]
|
|
boxABC a b c =
|
|
[ faceNC
|
|
, map (+.+.+ c) $ reverse faceNC
|
|
, faceNB
|
|
, map (+.+.+ b) $ reverse faceNB
|
|
, faceNA
|
|
, map (+.+.+ a) $ reverse faceNA
|
|
]
|
|
where
|
|
faceNC = rhombus b a
|
|
faceNB = rhombus a c
|
|
faceNA = rhombus c b
|
|
|
|
polyToPics :: Polyhedra -> [Picture]
|
|
polyToPics = map helpPoly3D . _pyFaces
|
|
|
|
helpPoly3D :: [(Point3, Point4)] -> Picture
|
|
--{-# INLINE helpPoly3D #-}
|
|
helpPoly3D vs = map f $ polyToTris vs
|
|
where
|
|
f (pos,col) = Verx pos col [] 0 polyNum
|
|
|
|
polysToPic :: [Polyhedra] -> Picture
|
|
polysToPic = pictures . concatMap polyToPics
|
|
|
|
polyToEdges :: Polyhedra -> [(Point3,Point3,Point3,Point3)]
|
|
polyToEdges = map denormalEdges . constructEdges . map (map fst) . _pyFaces
|
|
|
|
denormalEdges :: (Point3,Point3,Point3,Point3) -> (Point3,Point3,Point3,Point3)
|
|
denormalEdges (a,b,n,m) = (a,b,a - x, b - y)
|
|
where
|
|
x = crossProd (b - a) n
|
|
y = crossProd (a - b) m
|
|
|
|
|
|
polyToGeoRender :: Polyhedra -> [Point3]
|
|
polyToGeoRender = concatMap (polyToTris . map fst) . _pyFaces
|