diff --git a/hgeometry-examples/draw/Main.hs b/hgeometry-examples/draw/Main.hs index e2748cb5a..71390b473 100644 --- a/hgeometry-examples/draw/Main.hs +++ b/hgeometry-examples/draw/Main.hs @@ -16,7 +16,7 @@ import Test.QuickCheck type R = RealNumber 5 -renderGraph :: PlaneGraph QuickCheckWorld (Point 2 R) () () -> IpePage R +renderGraph :: CPlaneGraph QuickCheckWorld (Point 2 R) () () -> IpePage R renderGraph gr = fromContent $ concat [ [ iO $ defIO p | p <- gr^..vertices ] , [ iO $ defIO seg | seg <- gr^..edgeSegments ] diff --git a/hgeometry-examples/skia/GeometryStore.hs b/hgeometry-examples/skia/GeometryStore.hs index c1442ab27..e21494bcc 100644 --- a/hgeometry-examples/skia/GeometryStore.hs +++ b/hgeometry-examples/skia/GeometryStore.hs @@ -39,7 +39,7 @@ data Geom = G_Point (Point 2 R :+ Attributes (Point 2 R)) data MyWorld -type PlaneGraph' r = PlaneGraph MyWorld (Point 2 r) PolygonEdgeType PolygonFaceData +type PlaneGraph' r = CPlaneGraph MyWorld (Point 2 r) PolygonEdgeType PolygonFaceData -------------------------------------------------------------------------------- diff --git a/hgeometry-examples/skia/Model.hs b/hgeometry-examples/skia/Model.hs index 76418bbcd..96a956564 100644 --- a/hgeometry-examples/skia/Model.hs +++ b/hgeometry-examples/skia/Model.hs @@ -78,7 +78,7 @@ currentStatus m1 m2 -- in planeGraphs data MyWorld -type PlaneGraph' r = PlaneGraph MyWorld (Point 2 r) PolygonEdgeType PolygonFaceData +type PlaneGraph' r = CPlaneGraph MyWorld (Point 2 r) PolygonEdgeType PolygonFaceData -------------------------------------------------------------------------------- -- * Data Type representing all our modal data diff --git a/hgeometry-examples/triangulateWorld/Main.hs b/hgeometry-examples/triangulateWorld/Main.hs index a220ad52a..b21f08e81 100644 --- a/hgeometry-examples/triangulateWorld/Main.hs +++ b/hgeometry-examples/triangulateWorld/Main.hs @@ -79,7 +79,7 @@ mainWith (Options inFile outFile) = do intersections' :: Set.Set (Point 2 R) intersections' = foldMap computeIntersections polies - subdivs :: [PlaneGraph PX (Point 2 R) _ _] + subdivs :: [CPlaneGraph PX (Point 2 R) _ _] subdivs = map (\(pg :+ _) -> triangulate pg) polies' triangles' :: [SimplePolygon (Point 2 R :+ _)] diff --git a/hgeometry/hgeometry.cabal b/hgeometry/hgeometry.cabal index 58284ca56..909845238 100644 --- a/hgeometry/hgeometry.cabal +++ b/hgeometry/hgeometry.cabal @@ -75,7 +75,7 @@ common all-setup , file-io >= 0.1 && < 1 , indexed-traversable >= 0.1.3 && < 1 , vector-builder >= 0.3.8 && < 1 - , HsYAML >= 0.2 && < 1 + -- , HsYAML >= 0.2 && < 1 , semialign >= 1.3 && < 1.4 , these >= 1.0.1 && < 1.3 , subcategories >= 0.2 && < 0.3 @@ -356,6 +356,7 @@ library HGeometry.PlaneGraph HGeometry.PlaneGraph.Class + HGeometry.PlaneGraph.Connected HGeometry.Polygon HGeometry.Polygon.Class @@ -446,7 +447,8 @@ library HGeometry.Polygon.Convex.MinkowskiSum HGeometry.Polygon.Triangulation.Types - HGeometry.PlaneGraph.Type + -- HGeometry.PlaneGraph.Type + HGeometry.PlaneGraph.Connected.Type HGeometry.LineSegment.Intersection.Types diff --git a/hgeometry/point/src/HGeometry/Point/PointF.hs b/hgeometry/point/src/HGeometry/Point/PointF.hs index 14123b9f3..2a0acc55c 100644 --- a/hgeometry/point/src/HGeometry/Point/PointF.hs +++ b/hgeometry/point/src/HGeometry/Point/PointF.hs @@ -24,7 +24,7 @@ import Data.Proxy import qualified Data.Vector.Generic as G import qualified Data.Vector.Generic.Mutable as GM import qualified Data.Vector.Unboxed as U -import Data.YAML +-- import Data.YAML import GHC.Generics (Generic) import GHC.TypeLits import HGeometry.Point.Class @@ -38,7 +38,8 @@ import Text.Read (Read (..), readListPrecDefault) -- | A Point wraps a vector newtype PointF v = Point { toVec :: v } deriving stock (Generic) - deriving newtype ( Eq, Ord, Random, NFData, Bounded, Enum, FromYAML, ToYAML + deriving newtype ( Eq, Ord, Random, NFData, Bounded, Enum + -- , FromYAML, ToYAML , ToJSON, FromJSON ) -- don't derive functor, or so here. since that will be confusing. diff --git a/hgeometry/src-quickcheck/HGeometry/PlaneGraph/Instances.hs b/hgeometry/src-quickcheck/HGeometry/PlaneGraph/Instances.hs index d80bcf4ad..84e567498 100644 --- a/hgeometry/src-quickcheck/HGeometry/PlaneGraph/Instances.hs +++ b/hgeometry/src-quickcheck/HGeometry/PlaneGraph/Instances.hs @@ -57,7 +57,7 @@ data QuickCheckWorld instance ( Arbitrary r , Ord r, Fractional r , Show r - ) => Arbitrary (PlaneGraph QuickCheckWorld (Point 2 r) () ()) where + ) => Arbitrary (CPlaneGraph QuickCheckWorld (Point 2 r) () ()) where arbitrary = arbitraryPlaneGraph Proxy -- general strategy: @@ -73,7 +73,7 @@ arbitraryPlaneGraph :: forall proxy s r. ( Ord r, Fractional r, Arbitrary r , Show r ) - => proxy s -> Gen (PlaneGraph s (Point 2 r) () ()) + => proxy s -> Gen (CPlaneGraph s (Point 2 r) () ()) arbitraryPlaneGraph proxy = do n <- scale (*2) arbitrary (pts :: NonEmpty (Point 2 r)) <- genNDistinct (max 10 n) arbitrary @@ -137,8 +137,8 @@ witherGraphTo vs (Graph gr) = Graph $ fmap removeEdges m -- \(O(n\log n)\) toPlaneGraph :: (Ord r, Foldable1 f) => proxy s - -> GGraph f (Point 2 r) v e -> PlaneGraph s (Point 2 r) () () -toPlaneGraph _ (Graph m) = PlaneGraph $ (planarGraph theDarts)&vertexData .~ vtxData + -> GGraph f (Point 2 r) v e -> CPlaneGraph s (Point 2 r) () () +toPlaneGraph _ (Graph m) = CPlaneGraph $ (planarGraph theDarts)&vertexData .~ vtxData where vtxData = Vector.fromNonEmptyN1 (length m) (NEMap.keys m) diff --git a/hgeometry/src/HGeometry/Plane/LowerEnvelope/Connected/Graph.hs b/hgeometry/src/HGeometry/Plane/LowerEnvelope/Connected/Graph.hs index af450992e..442c309bc 100644 --- a/hgeometry/src/HGeometry/Plane/LowerEnvelope/Connected/Graph.hs +++ b/hgeometry/src/HGeometry/Plane/LowerEnvelope/Connected/Graph.hs @@ -27,7 +27,7 @@ import HGeometry.HyperPlane.Class import HGeometry.HyperPlane.NonVertical import HGeometry.Plane.LowerEnvelope.Connected.MonoidalMap import HGeometry.Plane.LowerEnvelope.Connected.Type -import HGeometry.PlaneGraph.Type (E(..)) +import HGeometry.PlaneGraph.Connected.Type (E(..)) import HGeometry.Point import HGeometry.Vector import Hiraffe.AdjacencyListRep.Map diff --git a/hgeometry/src/HGeometry/PlaneGraph.hs b/hgeometry/src/HGeometry/PlaneGraph.hs index 81b5fc0a0..fa49dc45e 100644 --- a/hgeometry/src/HGeometry/PlaneGraph.hs +++ b/hgeometry/src/HGeometry/PlaneGraph.hs @@ -1,6 +1,6 @@ -------------------------------------------------------------------------------- -- | --- Module : HGeometry.PlaneGraph +-- Module : HGeometry.PlaneGraph.Connected -- Copyright : (C) Frank Staals -- License : see the LICENSE file -- Maintainer : Frank Staals @@ -12,13 +12,13 @@ module HGeometry.PlaneGraph ( module Hiraffe.Graph.Class , module HGeometry.PlaneGraph.Class , module Hiraffe.PlanarGraph.Class - , PlaneGraph(..) + , CPlaneGraph(..) , fromAdjacencyRep , fromConnectedSegments ) where import HGeometry.PlaneGraph.Class -import HGeometry.PlaneGraph.Type +import HGeometry.PlaneGraph.Connected import Hiraffe.Graph.Class import Hiraffe.PlanarGraph.Class diff --git a/hgeometry/src/HGeometry/PlaneGraph/Class.hs b/hgeometry/src/HGeometry/PlaneGraph/Class.hs index d4e9bfd66..61f934f6d 100644 --- a/hgeometry/src/HGeometry/PlaneGraph/Class.hs +++ b/hgeometry/src/HGeometry/PlaneGraph/Class.hs @@ -50,6 +50,8 @@ class ( PlanarGraph_ planeGraph , vertex ~ Vertex planeGraph , Point_ vertex 2 (NumType vertex) , NumType vertex ~ NumType planeGraph + -- , HasVertices graph graph + , HasEdges planeGraph planeGraph ) => PlaneGraph_ planeGraph vertex | planeGraph -> vertex where {-# MINIMAL fromEmbedding #-} diff --git a/hgeometry/src/HGeometry/PlaneGraph/Connected.hs b/hgeometry/src/HGeometry/PlaneGraph/Connected.hs new file mode 100644 index 000000000..88d262c0e --- /dev/null +++ b/hgeometry/src/HGeometry/PlaneGraph/Connected.hs @@ -0,0 +1,26 @@ +-------------------------------------------------------------------------------- +-- | +-- Module : HGeometry.PlaneGraph.Connected +-- Copyright : (C) Frank Staals +-- License : see the LICENSE file +-- Maintainer : Frank Staals +-- +-- Plane Graphs, i.e. embedded planar graphs. +-- +-------------------------------------------------------------------------------- +module HGeometry.PlaneGraph.Connected + ( module Hiraffe.Graph.Class + , module HGeometry.PlaneGraph.Class + , module Hiraffe.PlanarGraph.Class + , CPlaneGraph(..) + , fromAdjacencyRep + , fromConnectedSegments + ) where + +import HGeometry.PlaneGraph.Class +import HGeometry.PlaneGraph.Connected.Type +import Hiraffe.Graph.Class +import Hiraffe.PlanarGraph.Class + + +-------------------------------------------------------------------------------- diff --git a/hgeometry/src/HGeometry/PlaneGraph/Connected/Type.hs b/hgeometry/src/HGeometry/PlaneGraph/Connected/Type.hs new file mode 100644 index 000000000..ea97ce7fc --- /dev/null +++ b/hgeometry/src/HGeometry/PlaneGraph/Connected/Type.hs @@ -0,0 +1,263 @@ +{-# LANGUAGE UndecidableInstances #-} +-------------------------------------------------------------------------------- +-- | +-- Module : HGeometry.PlaneGraph.Connected.Type +-- Copyright : (C) Frank Staals +-- License : see the LICENSE file +-- Maintainer : Frank Staals +-- +-- Type type for planar graphs embedded in \(\mathbb{R}^2\). For functions that +-- export faces and edges etc, we assume the graph has a (planar) straight line +-- embedding. +-- +-------------------------------------------------------------------------------- +module HGeometry.PlaneGraph.Connected.Type + ( CPlaneGraph(..) + , fromAdjacencyRep + , fromConnectedSegments + -- , VertexData(VertexData), location + + , E(..) + ) where + +import Control.Lens hiding (holes, holesOf, (.=)) +import Data.Coerce +import Data.Foldable1 +import Data.Foldable1.WithIndex +import qualified Data.List.NonEmpty as NonEmpty +import qualified Data.Map as Map +import qualified Data.Map.NonEmpty as NEMap +import qualified Data.Vector.NonEmpty as Vector +import GHC.Generics (Generic) +import HGeometry.Box +import HGeometry.Foldable.Sort (sortBy ) +import HGeometry.LineSegment +import HGeometry.Plane.LowerEnvelope.Connected.MonoidalMap +import HGeometry.PlaneGraph.Class +import HGeometry.Point +import HGeometry.Properties +import HGeometry.Transformation +import HGeometry.Vector +import Hiraffe.AdjacencyListRep.Map +import Hiraffe.Graph.Class +import Hiraffe.PlanarGraph.Class +import Hiraffe.PlanarGraph.Connected ( CPlanarGraph, World(..) + , DartId, VertexId, FaceId + ) +import qualified Hiraffe.PlanarGraph.Connected as PG +import qualified Hiraffe.PlanarGraph.Dart as Dart + + +-------------------------------------------------------------------------------- +-- * The CPlaneGraph type + +-- | An Embedded, *connected*, planar graph +newtype CPlaneGraph s v e f = + CPlaneGraph (CPlanarGraph Primal s v e f) + deriving stock (Show,Eq,Generic) + +type instance NumType (CPlaneGraph s v e f) = NumType v +type instance Dimension (CPlaneGraph s v e f) = 2 + +-- | Iso to access the graph +_CPlanarGraph :: Iso (CPlaneGraph s v e f) (CPlaneGraph s v' e' f') + (CPlanarGraph Primal s v e f) (CPlanarGraph Primal s v' e' f') +_CPlanarGraph = coerced +{-# INLINE _CPlanarGraph #-} + +---------------------------------------- + +instance HasVertices' (CPlaneGraph s v e f) where + type Vertex (CPlaneGraph s v e f) = v + type VertexIx (CPlaneGraph s v e f) = VertexId s + vertexAt i = _CPlanarGraph.vertexAt i + +instance HasVertices (CPlaneGraph s v e f) (CPlaneGraph s v' e f) where + vertices = _CPlanarGraph.vertices + +---------------------------------------- + +instance HasDarts' (CPlaneGraph s v e f) where + type Dart (CPlaneGraph s v e f) = e + type DartIx (CPlaneGraph s v e f) = DartId s + dartAt i = _CPlanarGraph.dartAt i + +instance HasDarts (CPlaneGraph s v e f) (CPlaneGraph s v e' f) where + darts = _CPlanarGraph.darts + +---------------------------------------- + +instance HasEdges' (CPlaneGraph s v e f) where + type Edge (CPlaneGraph s v e f) = e + type EdgeIx (CPlaneGraph s v e f) = DartId s + edgeAt d = _CPlanarGraph.edgeAt d + +instance HasEdges (CPlaneGraph s v e f) (CPlaneGraph s v e f) where + edges = _CPlanarGraph.edges + +---------------------------------------- + +instance HasFaces' (CPlaneGraph s v e f) where + type Face (CPlaneGraph s v e f) = f + type FaceIx (CPlaneGraph s v e f) = FaceId s + faceAt fi = _CPlanarGraph.faceAt fi + + +instance HasFaces (CPlaneGraph s v e f) (CPlaneGraph s v e f') where + faces = _CPlanarGraph.faces + +---------------------------------------- +instance DiGraph_ (CPlaneGraph s v e f) where + endPoints (CPlaneGraph g) = endPoints g + twinDartOf d = twinOf d . to Just + outgoingDartsOf v = _CPlanarGraph.outgoingDartsOf v + +instance ConstructableDiGraph_ (CPlaneGraph s v e f) where + type DiGraphFromAdjListExtraConstraints (CPlaneGraph s v e f) h = (f ~ (), Foldable1 h) + + -- | The vertices are expected to have their adjacencies in CCW order. + diGraphFromAdjacencyLists = CPlaneGraph . diGraphFromAdjacencyLists + -- TODO: we should probably use some toEmbedding here as well I think + + +instance BidirGraph_ (CPlaneGraph s v e f) where + twinOf d = to $ const (PG.twin d) + getPositiveDart (CPlaneGraph g) e = getPositiveDart g e + + +-- | Computes the cyclic order of adjacencies around each vertex. +-- +-- \(O(n \log n)\) +toEmbedding :: ( Foldable1 g, Functor g, Foldable h, Functor h + , vi ~ VertexIx (CPlaneGraph s v e f) + , v ~ Vertex (CPlaneGraph s v e f) + , e ~ Edge (CPlaneGraph s v e f) + , GraphFromAdjListExtraConstraints (CPlaneGraph s v e f) h + , Point_ v 2 r, Ord r, Num r + ) => g (vi, v, h (vi, e)) -> g (vi, v, Vector.NonEmptyVector (vi, e)) +toEmbedding vs = fmap sortAround' vs + where + vertexLocs = foldMap (\(vi,v,_) -> Map.singleton vi v) vs + sortAround' (vi,v,adjs) = (vi,v, Vector.unsafeFromVector $ sortBy (ccwCmpAround' v) adjs) + ccwCmpAround' v (ui,_) (wi,_) = ccwCmpAround v (vertexLocs Map.! ui) (vertexLocs Map.! wi) + + + +instance ( Point_ v 2 (NumType v) + , Ord (NumType v), Num (NumType v) + ) => Graph_ (CPlaneGraph s v e f) where + neighboursOf u = _CPlanarGraph.neighboursOf u + incidentEdgesOf u = _CPlanarGraph.incidentEdgesOf u + +instance ( Point_ v 2 (NumType v) + , Ord (NumType v), Num (NumType v) + ) => ConstructableGraph_ (CPlaneGraph s v e f) where + type GraphFromAdjListExtraConstraints (CPlaneGraph s v e f) h = (f ~ (), Foldable1 h) + + fromAdjacencyLists = fromEmbedding . toEmbedding + + +instance ( Point_ v 2 (NumType v) + , Ord (NumType v), Num (NumType v) + ) => PlanarGraph_ (CPlaneGraph s v e f) where + type DualGraphOf (CPlaneGraph s v e f) = CPlanarGraph Dual s f e v + + dualGraph = dualGraph . coerce @_ @(CPlanarGraph Primal s v e f) + + leftFaceOf d = _CPlanarGraph.leftFaceOf d + rightFaceOf d = _CPlanarGraph.rightFaceOf d + + nextDartOf d = _CPlanarGraph.nextDartOf d + prevDartOf d = _CPlanarGraph.prevDartOf d + + boundaryDartOf f = _CPlanarGraph.boundaryDartOf f + boundaryDarts f = boundaryDarts f . coerce @_ @(CPlanarGraph Primal s v e f) + + +instance ( Point_ v 2 (NumType v) + , Ord (NumType v), Num (NumType v) + ) => PlaneGraph_ (CPlaneGraph s v e f) v where + fromEmbedding = CPlaneGraph . fromAdjacencyLists + +instance ( Point_ v 2 r, Point_ v' 2 r' + ) => HasPoints (CPlaneGraph s v e f) + (CPlaneGraph s v' e f) v v' where + allPoints = vertices + +instance ( Point_ v 2 r + , Ord r, Num r + ) => IsBoxable (CPlaneGraph s v e f) + +instance ( Point_ v 2 r + , DefaultTransformByConstraints (CPlaneGraph s v e f) 2 r + ) => IsTransformable (CPlaneGraph s v e f) + + + + -- boundingBox = boundingBoxList' . F.toList . fmap (^._2.location) . vertices + + +-------------------------------------------------------------------------------- + +-- | Constructs a connected plane graph +-- +-- pre: The segments form a single connected component +-- No two segments partially overlap. +-- +-- running time: \(O(n\log n)\) +fromConnectedSegments :: ( Foldable1 f, Ord r, Num r + , LineSegment_ lineSegment point + , Point_ point 2 r + ) + => f lineSegment + -> CPlaneGraph s (NonEmpty.NonEmpty point) lineSegment () +fromConnectedSegments segs = CPlaneGraph $ + (PG.planarGraph theDarts)&PG.vertexData .~ vtxData + where + -- to get the darts we simply convert the NEMap (_, NEMap _ (dart, seg)) into + -- a NonEmpty (NonEmpty (dart, seg)) + theDarts = toNonEmpty . snd <$> verts + vtxData = Vector.fromNonEmpty $ fst <$> verts + + -- Collects all edges per vertex + verts = toNonEmpty . ifoldMap1 f $ toNonEmpty segs + + -- Creates two vertices with one edge each ; combines them into a single Map + f i seg = let u = seg^.start + v = seg^.end + d = Dart.Dart (Dart.Arc i) Dart.Positive + in singleton (u^.asPoint) (vtx (d ,seg) u v) + <> singleton (v^.asPoint) (vtx (Dart.twin d,seg) v u) + + singleton k v = MonoidalNEMap $ NEMap.singleton k v + +-- | Helper type to represent the vertex data of a vertex. The NEMap +-- represents the edges ordered cyclically around the vertex +type VtxData v r e = (v, NEMap.NEMap (E r) e) + +-- | Creates the vertex data +vtx :: (Point_ point 2 r, Ord r, Num r) + => e -> point -> point -> VtxData (NonEmpty.NonEmpty point) r e +vtx e p q = (NonEmpty.singleton p, NEMap.singleton (E $ q .-. p) e) + +-------------------------------------------------------------------------------- + +-- | Given a connected plane graph in adjacency list format; convert it into an actual +-- CPlaneGraph. +-- +-- \(O(n\log n)\) +fromAdjacencyRep :: (Point_ vertex 2 r, Ord i, Foldable1 f) + => proxy s -> GGraph f i vertex e -> CPlaneGraph s vertex e () +fromAdjacencyRep proxy = CPlaneGraph . PG.fromAdjacencyRep proxy + + +-------------------------------------------------------------------------------- + +-- | Helper type to sort vectors cyclically around the origine +newtype E r = E (Vector 2 r) + deriving newtype (Show) + +instance (Ord r, Num r) => Eq (E r) where + a == b = a `compare` b == EQ +instance (Ord r, Num r) => Ord (E r) where + (E v) `compare` (E u) = ccwCmpAroundWith (Vector2 0 1) (origin :: Point 2 r) (Point v) (Point u) diff --git a/hgeometry/src/HGeometry/PlaneGraph/Type.hs b/hgeometry/src/HGeometry/PlaneGraph/Type.hs index 40b817032..7d7db7cfa 100644 --- a/hgeometry/src/HGeometry/PlaneGraph/Type.hs +++ b/hgeometry/src/HGeometry/PlaneGraph/Type.hs @@ -28,7 +28,6 @@ import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Map as Map import qualified Data.Map.NonEmpty as NEMap import qualified Data.Vector.NonEmpty as Vector -import Data.YAML import GHC.Generics (Generic) import HGeometry.Box import HGeometry.Foldable.Sort (sortBy ) @@ -44,26 +43,27 @@ import Hiraffe.Graph.Class import Hiraffe.PlanarGraph ( PlanarGraph, World(..) , DartId, VertexId, FaceId ) -import qualified Hiraffe.PlanarGraph as PG import Hiraffe.PlanarGraph.Class +import qualified Hiraffe.PlanarGraph as PG import qualified Hiraffe.PlanarGraph.Dart as Dart +-- import Data.YAML + -------------------------------------------------------------------------------- -- * The PlaneGraph type -- | An Embedded, *connected*, planar graph -newtype PlaneGraph s v e f = - PlaneGraph (PlanarGraph s Primal v e f) +newtype PlaneGraph s v e f = PlaneGraph (PlanarGraph Primal s v e f) deriving stock (Show,Eq,Generic) - deriving newtype (ToYAML,FromYAML) + -- deriving newtype (ToYAML,FromYAML) type instance NumType (PlaneGraph s v e f) = NumType v type instance Dimension (PlaneGraph s v e f) = 2 -- | Iso to access the graph _PlanarGraph :: Iso (PlaneGraph s v e f) (PlaneGraph s v' e' f') - (PlanarGraph s Primal v e f) (PlanarGraph s Primal v' e' f') + (PlanarGraph Primal s v e f) (PlanarGraph Primal s v' e' f') _PlanarGraph = coerced {-# INLINE _PlanarGraph #-} @@ -110,15 +110,17 @@ instance HasFaces (PlaneGraph s v e f) (PlaneGraph s v e f') where ---------------------------------------- instance DiGraph_ (PlaneGraph s v e f) where + endPoints (PlaneGraph g) = endPoints g + twinDartOf d = twinOf d . to Just + outgoingDartsOf v = _PlanarGraph.outgoingDartsOf v + +instance ConstructableDiGraph_ (PlaneGraph s v e f) where type DiGraphFromAdjListExtraConstraints (PlaneGraph s v e f) h = (f ~ (), Foldable1 h) -- | The vertices are expected to have their adjacencies in CCW order. diGraphFromAdjacencyLists = PlaneGraph . diGraphFromAdjacencyLists -- TODO: we should probably use some toEmbedding here as well I think - endPoints (PlaneGraph g) = endPoints g - twinDartOf d = twinOf d . to Just - outgoingDartsOf v = _PlanarGraph.outgoingDartsOf v instance BidirGraph_ (PlaneGraph s v e f) where twinOf d = to $ const (PG.twin d) @@ -146,19 +148,22 @@ toEmbedding vs = fmap sortAround' vs instance ( Point_ v 2 (NumType v) , Ord (NumType v), Num (NumType v) ) => Graph_ (PlaneGraph s v e f) where - type GraphFromAdjListExtraConstraints (PlaneGraph s v e f) h = (f ~ (), Foldable1 h) - - fromAdjacencyLists = fromEmbedding . toEmbedding - neighboursOf u = _PlanarGraph.neighboursOf u incidentEdgesOf u = _PlanarGraph.incidentEdgesOf u instance ( Point_ v 2 (NumType v) , Ord (NumType v), Num (NumType v) + ) => ConstructableGraph_ (PlaneGraph s v e f) where + type GraphFromAdjListExtraConstraints (PlaneGraph s v e f) h = (f ~ (), Foldable1 h) + fromAdjacencyLists = fromEmbedding . toEmbedding + +instance ( Point_ v 2 (NumType v) + , Ord (NumType v), Num (NumType v) + ) => PlanarGraph_ (PlaneGraph s v e f) where - type DualGraphOf (PlaneGraph s v e f) = PlanarGraph s Dual f e v + type DualGraphOf (PlaneGraph s v e f) = PlanarGraph Dual s f e v - dualGraph = dualGraph . coerce @_ @(PlanarGraph s Primal v e f) + dualGraph = dualGraph . coerce @_ @(PlanarGraph Primal s v e f) leftFaceOf d = _PlanarGraph.leftFaceOf d rightFaceOf d = _PlanarGraph.rightFaceOf d @@ -167,7 +172,7 @@ instance ( Point_ v 2 (NumType v) prevDartOf d = _PlanarGraph.prevDartOf d boundaryDartOf f = _PlanarGraph.boundaryDartOf f - boundaryDarts f = boundaryDarts f . coerce @_ @(PlanarGraph s Primal v e f) + boundaryDarts f = boundaryDarts f . coerce @_ @(PlanarGraph Primal s v e f) instance ( Point_ v 2 (NumType v) diff --git a/hgeometry/src/HGeometry/Polygon/Triangulation.hs b/hgeometry/src/HGeometry/Polygon/Triangulation.hs index c606ad733..1cf279a5a 100644 --- a/hgeometry/src/HGeometry/Polygon/Triangulation.hs +++ b/hgeometry/src/HGeometry/Polygon/Triangulation.hs @@ -34,7 +34,7 @@ import Hiraffe.PlanarGraph triangulate :: forall s polygon point r. (SimplePolygon_ polygon point r, Ord r, Num r) => polygon - -> PlaneGraph s point PolygonEdgeType PolygonFaceData + -> CPlaneGraph s point PolygonEdgeType PolygonFaceData triangulate pg = constructGraph pg (computeDiagonals pg) -- | Computes a set of diagaonals that together triangulate the input polygon @@ -46,7 +46,7 @@ computeDiagonals :: forall polygon point r. => polygon -> [Diagonal polygon] computeDiagonals pg = monotoneDiags <> extraDiags where - monotoneSubdiv :: PlaneGraph () point PolygonEdgeType PolygonFaceData + monotoneSubdiv :: CPlaneGraph () point PolygonEdgeType PolygonFaceData monotoneSubdiv = MM.makeMonotone @() pg -- use some arbitrary proxy type diff --git a/hgeometry/src/HGeometry/Polygon/Triangulation/MakeMonotone.hs b/hgeometry/src/HGeometry/Polygon/Triangulation/MakeMonotone.hs index 58c0e8ba9..1a6da556d 100644 --- a/hgeometry/src/HGeometry/Polygon/Triangulation/MakeMonotone.hs +++ b/hgeometry/src/HGeometry/Polygon/Triangulation/MakeMonotone.hs @@ -22,7 +22,7 @@ import qualified Data.Vector as Vector import HGeometry.Ext import HGeometry.Foldable.Sort import HGeometry.LineSegment -import HGeometry.PlaneGraph +import HGeometry.PlaneGraph.Connected import HGeometry.Point import HGeometry.Polygon.Class import HGeometry.Polygon.Simple.Class @@ -41,7 +41,7 @@ import qualified VectorBuilder.Vector as Builder makeMonotone :: forall s polygon point r. (SimplePolygon_ polygon point r, Ord r, Num r) => polygon - -> PlaneGraph s point PolygonEdgeType PolygonFaceData + -> CPlaneGraph s point PolygonEdgeType PolygonFaceData makeMonotone pg = constructGraph pg (computeDiagonals pg) diff --git a/hgeometry/src/HGeometry/Polygon/Triangulation/TriangulateMonotone.hs b/hgeometry/src/HGeometry/Polygon/Triangulation/TriangulateMonotone.hs index 424472e3d..e02b39b38 100644 --- a/hgeometry/src/HGeometry/Polygon/Triangulation/TriangulateMonotone.hs +++ b/hgeometry/src/HGeometry/Polygon/Triangulation/TriangulateMonotone.hs @@ -31,7 +31,7 @@ import HGeometry.Combinatorial.Util import HGeometry.Ext import HGeometry.Vector (Vector(Vector2)) -- import HGeometry.PlanarSubdivision.Basic (PlanarSubdivision, PolygonFaceData) -import HGeometry.PlaneGraph (PlaneGraph) +import HGeometry.PlaneGraph.Connected (CPlaneGraph) import HGeometry.Point import HGeometry.Polygon.Class import HGeometry.Polygon.Simple.Class @@ -55,7 +55,7 @@ triangulate :: forall s yMonotonePolygon point r. (YMonotonePolygon_ yMonotonePolygon point r, Ord r, Num r ) => yMonotonePolygon - -> PlaneGraph s point PolygonEdgeType PolygonFaceData + -> CPlaneGraph s point PolygonEdgeType PolygonFaceData triangulate pg = constructGraph pg (computeDiagonals pg) -- TODO: Find a way to construct the graph in O(n) time. diff --git a/hgeometry/src/HGeometry/Polygon/Triangulation/Types.hs b/hgeometry/src/HGeometry/Polygon/Triangulation/Types.hs index 1a6ba0cb3..55963bbcf 100644 --- a/hgeometry/src/HGeometry/Polygon/Triangulation/Types.hs +++ b/hgeometry/src/HGeometry/Polygon/Triangulation/Types.hs @@ -135,12 +135,12 @@ constructGraph :: forall s polygon point r f. ) => polygon -> f (Diagonal polygon) - -> PlaneGraph s point PolygonEdgeType PolygonFaceData + -> CPlaneGraph s point PolygonEdgeType PolygonFaceData constructGraph pg diags = gr&faces %@~ computeFaceLabel -- constructGraph pg diags = gr&faces %@~ computeFaceLabel where -- | Note that we use fromAdjacencyLists - gr = fromAdjacencyLists adjLists :: PlaneGraph s point PolygonEdgeType () + gr = fromAdjacencyLists adjLists :: CPlaneGraph s point PolygonEdgeType () adjLists = uncurry collectDiags <$> itoNonEmptyOf outerBoundaryWithNeighbours pg diff --git a/hgeometry/test-with-ipe/test/PlaneGraph/RenderSpec.hs b/hgeometry/test-with-ipe/test/PlaneGraph/RenderSpec.hs index bf561b807..e87fce870 100644 --- a/hgeometry/test-with-ipe/test/PlaneGraph/RenderSpec.hs +++ b/hgeometry/test-with-ipe/test/PlaneGraph/RenderSpec.hs @@ -80,7 +80,7 @@ spec = describe "render planegraph tests" $ do goldenWith [osp|data/test-with-ipe/golden/PlaneGraph|] (ipeContentGolden { name = [osp|smallPlaneGraph|]}) (drawGraph smallGraph) - -- eg <- runIO $ decodeYAMLFile [osp|myPlaneGraph.yaml|] + -- eg <- runIO $ decodeYAMLFile [osp|myPlaneGraph.json|] -- let myPlaneGraph = case eg of -- Left err -> error (show err) -- Right (g :: PlaneGraph MyWorld (Point 2 R) Text.Text Text.Text) -> g @@ -165,8 +165,8 @@ tshow = Text.pack . show data SmallWorld -smallGraph :: PlaneGraph SmallWorld (Point 2 R :+ Int) Text.Text Text.Text -smallGraph = PlaneGraph $ AdjRep.fromAdjRep @SmallWorld small +smallGraph :: CPlaneGraph SmallWorld (Point 2 R :+ Int) Text.Text Text.Text +smallGraph = CPlaneGraph $ AdjRep.fromAdjRep @SmallWorld small where small :: AdjRep.Gr (AdjRep.Vtx (Point 2 R :+ Int) Text.Text) (AdjRep.Face Text.Text) small = AdjRep.Gr diff --git a/hgeometry/test-with-ipe/test/Polygon/Triangulation/TriangulateSpec.hs b/hgeometry/test-with-ipe/test/Polygon/Triangulation/TriangulateSpec.hs index 55b17b720..aa54d5363 100644 --- a/hgeometry/test-with-ipe/test/Polygon/Triangulation/TriangulateSpec.hs +++ b/hgeometry/test-with-ipe/test/Polygon/Triangulation/TriangulateSpec.hs @@ -7,7 +7,7 @@ import Control.Lens import HGeometry import HGeometry.Ext import HGeometry.Number.Real.Rational -import HGeometry.PlaneGraph +import HGeometry.PlaneGraph.Connected import HGeometry.Polygon import HGeometry.Polygon.Simple import HGeometry.Polygon.Triangulation @@ -70,7 +70,7 @@ _drawGraph gr = theVertices <> theEdges <> theFaces theFaces = [] -- ifoldMapOf interiorFacePolygons (drawFace gr) gr graphPolygons :: (Ord r, Num r, Point_ point 2 r) - => PlaneGraph s point PolygonEdgeType PolygonFaceData + => CPlaneGraph s point PolygonEdgeType PolygonFaceData -> [SimplePolygon (Point 2 r)] graphPolygons gr = map (&vertices %~ view (core.asPoint)) $ gr^..interiorFacePolygons diff --git a/hgeometry/test/Polygon/TriangulateSpec.hs b/hgeometry/test/Polygon/TriangulateSpec.hs index 724f65066..14bc4e92d 100644 --- a/hgeometry/test/Polygon/TriangulateSpec.hs +++ b/hgeometry/test/Polygon/TriangulateSpec.hs @@ -84,7 +84,7 @@ isTriangle :: SimplePolygon (Point 2 R) -> Bool isTriangle = (== 3) . numVertices graphPolygons :: (Ord r, Num r, Point_ point 2 r) - => PlaneGraph s point PolygonEdgeType PolygonFaceData + => CPlaneGraph s point PolygonEdgeType PolygonFaceData -> [SimplePolygon (Point 2 r)] graphPolygons gr = map (&vertices %~ view (core.asPoint)) $ gr^..interiorFacePolygons diff --git a/hgeometry/vector/src/HGeometry/Vector/Type.hs b/hgeometry/vector/src/HGeometry/Vector/Type.hs index c3618723e..c905be5da 100644 --- a/hgeometry/vector/src/HGeometry/Vector/Type.hs +++ b/hgeometry/vector/src/HGeometry/Vector/Type.hs @@ -26,7 +26,7 @@ import Data.Proxy import Data.Semigroup.Foldable import Data.These import qualified Data.Vector as Array -import Data.YAML +-- import Data.YAML import Data.Zip import GHC.Generics (Generic) import GHC.TypeNats @@ -103,13 +103,13 @@ instance HasComponents (Vector 1 r) (Vector 1 s) where {-# INLINE components #-} -instance FromYAML r => FromYAML (Vector 1 r) where - -- node pos -> Parser - parseYAML node = withSeq "Vector1" f node - where - f = \case - [pos] -> Vector1 <$> parseYAML pos - _ -> failAtNode node "expected exactly 1 element" +-- instance FromYAML r => FromYAML (Vector 1 r) where +-- -- node pos -> Parser +-- parseYAML node = withSeq "Vector1" f node +-- where +-- f = \case +-- [pos] -> Vector1 <$> parseYAML pos +-- _ -> failAtNode node "expected exactly 1 element" instance FromJSON r => FromJSON (Vector 1 r) where parseJSON = withArray "Vector1" (f . Array.toList) @@ -160,12 +160,12 @@ instance Zip (Vector 2) where zipWith f (Vector2 x y) (Vector2 x' y') = Vector2 (f x x') (f y y') {-# INLINE zipWith #-} -instance FromYAML r => FromYAML (Vector 2 r) where - parseYAML node = withSeq "Vector2" f node - where - f = \case - [posX,posY] -> Vector2 <$> parseYAML posX <*> parseYAML posY - _ -> failAtNode node "expected exactly 2 elements" +-- instance FromYAML r => FromYAML (Vector 2 r) where +-- parseYAML node = withSeq "Vector2" f node +-- where +-- f = \case +-- [posX,posY] -> Vector2 <$> parseYAML posX <*> parseYAML posY +-- _ -> failAtNode node "expected exactly 2 elements" instance FromJSON r => FromJSON (Vector 2 r) where parseJSON = withArray "Vector2" (f . Array.toList) @@ -217,13 +217,13 @@ instance Zip (Vector 3) where zipWith f (Vector3 x y z) (Vector3 x' y' z') = Vector3 (f x x') (f y y') (f z z') {-# INLINE zipWith #-} -instance FromYAML r => FromYAML (Vector 3 r) where - -- node pos -> Parser - parseYAML node = withSeq "Vector3" f node - where - f = \case - [posX,posY,posZ] -> Vector3 <$> parseYAML posX <*> parseYAML posY <*> parseYAML posZ - _ -> failAtNode node "expected exactly 3 elements" +-- instance FromYAML r => FromYAML (Vector 3 r) where +-- -- node pos -> Parser +-- parseYAML node = withSeq "Vector3" f node +-- where +-- f = \case +-- [posX,posY,posZ] -> Vector3 <$> parseYAML posX <*> parseYAML posY <*> parseYAML posZ +-- _ -> failAtNode node "expected exactly 3 elements" instance FromJSON r => FromJSON (Vector 3 r) where parseJSON = withArray "Vector3" (f . Array.toList) @@ -283,14 +283,14 @@ instance Zip (Vector 4) where zipWith f (Vector4 x y z w) (Vector4 x' y' z' w') = Vector4 (f x x') (f y y') (f z z') (f w w') {-# INLINE zipWith #-} -instance FromYAML r => FromYAML (Vector 4 r) where - -- node pos -> Parser - parseYAML node = withSeq "Vector4" f node - where - f = \case - [posX,posY,posZ,posW] -> - Vector4 <$> parseYAML posX <*> parseYAML posY <*> parseYAML posZ <*> parseYAML posW - _ -> failAtNode node "expected exactly 4 elements" +-- instance FromYAML r => FromYAML (Vector 4 r) where +-- -- node pos -> Parser +-- parseYAML node = withSeq "Vector4" f node +-- where +-- f = \case +-- [posX,posY,posZ,posW] -> +-- Vector4 <$> parseYAML posX <*> parseYAML posY <*> parseYAML posZ <*> parseYAML posW +-- _ -> failAtNode node "expected exactly 4 elements" instance FromJSON r => FromJSON (Vector 4 r) where parseJSON = withArray "Vector4" (f . Array.toList) @@ -351,8 +351,8 @@ instance ( HasComponents (Vector d r) (Vector d r) -------------------------------------------------------------------------------- -instance (ToYAML r, HasComponents (Vector d r) (Vector d r)) => ToYAML (Vector d r) where - toYAML = toYAML . toListOf components +-- instance (ToYAML r, HasComponents (Vector d r) (Vector d r)) => ToYAML (Vector d r) where +-- toYAML = toYAML . toListOf components instance (ToJSON r, HasComponents (Vector d r) (Vector d r)) => ToJSON (Vector d r) where toJSON = toJSON . toListOf components