module Data.Geometry.PlanarSubdivision where
import Control.Lens
import qualified Data.BalBST as SS
import Data.Bifunctor.Apply
import qualified Data.CircularSeq as C
import Data.Ext
import qualified Data.Foldable as F
import Data.Geometry.Interval
import Data.Geometry.LineSegment
import Data.Geometry.Point
import Data.Geometry.Polygon
import Data.Geometry.Properties
import qualified Data.Map as M
import Data.PlanarGraph
import Data.PlaneGraph
import Data.Semigroup
import Data.Util
import qualified Data.Vector as V
data VertexData r v = VertexData { _location :: !(Point 2 r)
, _vData :: !v
} deriving (Show,Eq,Ord,Functor,Foldable,Traversable)
makeLenses ''VertexData
instance Bifunctor VertexData where
bimap f g (VertexData p v) = VertexData (fmap f p) (g v)
data EdgeType = Visible | Invisible deriving (Show,Read,Eq,Ord)
data EdgeData e = EdgeData { _edgeType :: !EdgeType
, _eData :: !e
} deriving (Show,Eq,Ord,Functor,Foldable,Traversable)
makeLenses ''EdgeData
data FaceData h f = FaceData { _holes :: [h]
, _fData :: !f
} deriving (Show,Eq,Ord,Functor,Foldable,Traversable)
makeLenses ''FaceData
newtype PlanarSubdivision s v e f r = PlanarSubdivision { _graph ::
PlanarGraph s Primal_ (VertexData r v) (EdgeData e) (FaceData (Dart s) f) }
deriving (Show,Eq)
makeLenses ''PlanarSubdivision
instance Functor (PlanarSubdivision s v e f) where
fmap f s = s&graph.vertexData.traverse.location %~ fmap f
fromPolygon :: proxy s
-> SimplePolygon p r
-> f
-> f
-> PlanarSubdivision s p () f r
fromPolygon p (SimplePolygon vs) iD oD = PlanarSubdivision g'
where
g = fromVertices p vs
fData' = V.fromList [FaceData [] iD, FaceData [] oD]
g' = g & faceData .~ fData'
& dartData.traverse._2 .~ EdgeData Visible ()
fromVertices :: proxy s
-> C.CSeq (Point 2 r :+ p)
-> PlanarGraph s Primal_ (VertexData r p) () ()
fromVertices _ vs = g&vertexData .~ vData'
where
n = length vs
g = planarGraph [ [ (Dart (Arc i) Positive, ())
, (Dart (Arc $ (i+1) `mod` n) Negative, ())
]
| i <- [0..(n1)]]
vData' = V.fromList . map (\(p :+ e) -> VertexData p e) . F.toList $ vs
fromConnectedSegments :: (Foldable f, Ord r, Num r)
=> proxy s
-> f (LineSegment 2 p r :+ EdgeData e)
-> PlanarSubdivision s [p] e () r
fromConnectedSegments px ss = PlanarSubdivision $
fromConnectedSegments' px ss & faceData.traverse %~ FaceData []
fromConnectedSegments' :: (Foldable f, Ord r, Num r)
=> proxy s
-> f (LineSegment 2 p r :+ e)
-> PlanarGraph s Primal_ (VertexData r [p]) e ()
fromConnectedSegments' _ ss = planarGraph dts & vertexData .~ vxData
where
pts = M.fromListWith (<>) . concatMap f . zipWith g [0..] . F.toList $ ss
f (s :+ e) = [ ( s^.start.core
, SP [s^.start.extra] [(s^.end.core) :+ h Positive e])
, ( s^.end.core
, SP [s^.end.extra] [(s^.start.core) :+ h Negative e])
]
g i (s :+ e) = s :+ (Arc i :+ e)
h d (a :+ e) = (Dart a d, e)
vts = map (\(p,sp) -> (p,map (^.extra) . sortArround (ext p) <$> sp))
. M.assocs $ pts
vxData = V.fromList . map (\(p,sp) -> VertexData p (sp^._1)) $ vts
dts = map (^._2._2) vts