PenroseKiteDart-1.4.1: Library to explore Penrose's Kite and Dart Tilings.
Copyright(c) Chris Reade 2021
LicenseBSD-style
Maintainerchrisreade@mac.com
Stabilityexperimental
Safe HaskellNone
LanguageGHC2021

Tgraph.Force

Description

This module includes force and tryForce plus related operations for testing and experimenting such as tryStepForce, tryAddHalfKite and tryAddHalfDart. It introduces BoundaryState and ForceState types and includes a Forcible class with instances for Tgraph, BoundaryState, and ForceState.

The module is made strict (to remove many space leaks).

Synopsis

Forcible class

class Forcible a where Source #

Forcing a Tgraph requires conversion to a BoundaryState (which records extra data) and then to a ForceState (which keeps track of possible updates during forcing). Thus we introduce a Forcible class which will have Tgraph, BoundaryState, ForceState as instances.

Forcible class has operations to (indirectly) implement forcing and single step forcing for any Forcible. The class operations are more general to allow for other force related operations to be generalised for use on any Forcible. For example tryAddHalfKite and tryAddHalfDart are implemented using tryChangeBoundaryWith.

Note that these operations are parameterised on an UpdateGenerator, which encapsulates the forcing rules to be used.

Methods

tryFSOpWith :: UpdateGenerator -> (ForceState -> Try ForceState) -> a -> Try a Source #

tryFSOpWith (try ForseState Operation with) when given an update generator, generalises a (try) ForceState operation to a (try) Forcible operation. The update generator is only used to initialise a ForceState when there is not one already available (i.e not used when the Forcible is a ForceState)

To improve performance of a sequence of force related operations, express each as a ForceState -> Try ForceState, then use (<=<) or (>=>) to combine and pass to tryFSOpWith. This ensures there are no unnecessary conversions between steps.

tryInitFSWith :: UpdateGenerator -> a -> Try ForceState Source #

tryInitFSWith (try initialising a ForceState with) when given an update generator tries to create an initial ForceState (ready for forcing) from a Forcible. Again, the update generator is not used when the instance is a ForceState.

tryChangeBoundaryWith :: UpdateGenerator -> (BoundaryState -> Try BoundaryChange) -> a -> Try a Source #

tryChangeBoundaryWith when given an update generator, converts a (try) BoundaryState changing operation to a (try) Forcible operation. The update generator is only used when the instance is a ForceState (to revise the update map in the result).

Instances

Instances details
Forcible TrackedTgraph Source #

TrackedTgraphs are Forcible

Instance details

Defined in Tgraph.Extras

Forcible BoundaryState Source #

BoundaryStates are Forcible

Instance details

Defined in Tgraph.Force

Forcible ForceState Source #

ForceStates are Forcible

Instance details

Defined in Tgraph.Force

Forcible Tgraph Source #

Tgraphs are Forcible

Instance details

Defined in Tgraph.Force

Generalised forcing

force :: Forcible a => a -> a Source #

The main force (partial) function using defaultAllUGen representing all 10 rules for updates. This raises an error on discovering a stuck/incorrect Forcible.

forceWith :: Forcible a => UpdateGenerator -> a -> a Source #

forceWith ugen: force using the given UpdateGenerator This raises an error on discovering a stuck/incorrect Forcible.

tryForce :: Forcible a => a -> Try a Source #

A try version of the main force function using defaultAllUGen representing all 10 rules for updates. This returns Left report on discovering a stuck Tgraph and Right a (with a the resulting forcible) otherwise.

tryForceWith :: Forcible a => UpdateGenerator -> a -> Try a Source #

try forcing using a given UpdateGenerator. tryForceWith uGen fs - does updates using uGen until there are no more updates. It produces Left report if it encounters a Forcible representing a stuck/incorrect Tgraph.

stepForce :: Forcible a => Int -> a -> a Source #

stepForce n a - produces an intermediate Forcible after n steps (n face additions) starting from Forcible a. It raises an error if it encounters a stuck/incorrect Forcible within n steps. If forcing finishes successfully in n or fewer steps, it will return that final Forcible.

tryStepForce :: Forcible a => Int -> a -> Try a Source #

tryStepForce n a - produces a (Right) intermediate Forcible after n steps (n face additions) starting from Forcible a. or a Left report if it encounters a stuck/incorrect Forcible within n steps. If forcing finishes successfully in n or fewer steps, it will return that final Forcible.

tryStepForceWith :: Forcible a => UpdateGenerator -> Int -> a -> Try a Source #

try a given number of force steps using a given UpdateGenerator.

tryFSOp :: Forcible a => (ForceState -> Try ForceState) -> a -> Try a Source #

A version of tryFSOpWith using defaultAllUGen representing all 10 rules for updates.

initFS :: Forcible a => a -> ForceState Source #

initialize a force state with the default UpdateGenerator. Raises an error if it finds a stuck Forcible.

tryInitFS :: Forcible a => a -> Try ForceState Source #

try to initialize a force state with the default UpdateGenerator. Returns a Left report if it finds a stuck Forcible.

tryChangeBoundary :: Forcible a => (BoundaryState -> Try BoundaryChange) -> a -> Try a Source #

specialises tryChangeBoundaryWith to the default update generator.

wholeTiles :: Forcible a => a -> a Source #

special case of forcing only half tiles to whole tiles

Explicitly Forced

data Forced a Source #

Forced a is a newtype (for a) to explicitly indicate that a is fully forced. This enables restriction of some functions that should only be applied to a fully forced Forcible.

To access the Forcible use: forgetF :: Forced a -> a

Create an explicitly Forced Forcible using forceF or tryForceF

Instances

Instances details
HasFaces a => HasFaces (Forced a) Source #

Extend HasFaces ops from a to Forced a

Instance details

Defined in Tgraph.Force

Show a => Show (Forced a) Source # 
Instance details

Defined in Tgraph.Force

Methods

showsPrec :: Int -> Forced a -> ShowS #

show :: Forced a -> String #

showList :: [Forced a] -> ShowS #

forgetF :: Forced a -> a Source #

forget the explicit Forced labelling

tryForceF :: Forcible a => a -> Try (Forced a) Source #

tryForceF is the same as tryForce except that the successful result is explitly indicated as Forced.

forceF :: Forcible a => a -> Forced a Source #

forceF is the same partial function as force except that the (successful) result is explitly indicated as Forced.

recoverGraphF :: Forced BoundaryState -> Forced Tgraph Source #

recoverGraphF is an explicitly forced version of recoverGraph

boundaryStateF :: Forced ForceState -> Forced BoundaryState Source #

boundaryStateF is an explicitly forced version of boundaryState

makeBoundaryStateF :: Forced Tgraph -> Forced BoundaryState Source #

makeBoundaryStateF is an explicitly forced version of makeBoundaryState

initFSF :: Forcible a => Forced a -> Forced ForceState Source #

initFSF is an explicitly forced version of initFS

labelAsForced :: a -> Forced a Source #

Constructs an explicitly Forced type.

WARNING: this should only be used when the argument is known to be a fully forced Forcible. Consider using forceF or tryForceF instead for safety reasons.

Force Related

addHalfKite :: Forcible a => Dedge -> a -> a Source #

addHalfKite is for adding a single half kite on a chosen boundary Dedge of a Forcible. The Dedge must be a boundary edge but the direction is not important as the correct direction is automatically calculated. It will raise an error if the edge is a dart join or if a conflict (stuck graph) is detected or if the edge is not a boundary edge.

tryAddHalfKite :: Forcible a => Dedge -> a -> Try a Source #

tryAddHalfKite is a version of addHalfKite which returns a Try with a Left report if it finds a stuck/incorrect graph, or if the edge is a dart join, or if the edge is not a boundary edge.

addHalfDart :: Forcible a => Dedge -> a -> a Source #

addHalfDart is for adding a single half dart on a chosen boundary Dedge of a Forcible. The Dedge must be a boundary edge but the direction is not important as the correct direction is automatically calculated. It will raise an error if the edge is a dart short edge or kite join or if a conflict (stuck graph) is detected or if the edge is not a boundary edge.

tryAddHalfDart :: Forcible a => Dedge -> a -> Try a Source #

tryAddHalfDart is a version of addHalfDart which returns a Try with a Left report if it finds a stuck/incorrect graph, or if the edge is a dart short edge or kite join, or if the edge is not a boundary edge.

Debug Step Forcing

tryOneStepWith :: UpdateGenerator -> ForceState -> Try (Maybe (ForceState, BoundaryChange)) Source #

tryOneStepWith uGen fs does one force step (used for debugging purposes). It returns either (1) a Right(Just (f,bc)) with a new ForceState f paired with a BoundaryChange bc (using uGen to revise updates in the final ForceState), or (2) a Right Nothing indicating forcing has finished and there are no more updates, or (3) a Left report for a stuck/incorrect graph.

tryOneStepForce :: ForceState -> Try (Maybe (ForceState, BoundaryChange)) Source #

tryOneStepForce is a special case of tryOneStepWith using defaultAllUGen (used for debugging).

Types for Forcing

data BoundaryState Source #

A BoundaryState records the boundary directed edges (directed so that faces are on LHS and exterior is on RHS) plus a mapping of boundary vertices to their incident faces, plus a mapping of boundary vertices to positions (using Tgraph.Prelude.locateVertices). It also keeps track of all the faces and the next vertex label to be used when adding a new vertex.

Constructors

BoundaryState 

Fields

data ForceState Source #

ForceState: The force state records information between executing single face updates during forcing (a BoundaryState and an UpdateMap).

Instances

Instances details
Forcible ForceState Source #

ForceStates are Forcible

Instance details

Defined in Tgraph.Force

HasFaces ForceState Source #

ForceState is in class HasFaces

Instance details

Defined in Tgraph.Force

Show ForceState Source # 
Instance details

Defined in Tgraph.Force

data BoundaryChange Source #

After a face addition to a BoundaryState (by either trySafeUpdate or tryUnsafeUpdate), a BoundaryChange records (1) the new BoundaryState (2) the list of directed edges that were, but are no longer on the boundary (1,2,or 3), (3) a list of boundary edges requiring updates to be recalculated - i.e the new boundary edges and their immediate neighbours (4,3,or 0). (4) the face that has been added.

Constructors

BoundaryChange 

Fields

Instances

Instances details
Show BoundaryChange Source # 
Instance details

Defined in Tgraph.Force

data Update Source #

An Update is either safe or unsafe. A safe update has a new face involving 3 existing vertices. An unsafe update has a makeFace function to create the new face when given a fresh third vertex.

Instances

Instances details
Show Update Source #

0 is used as a dummy variable to show unsafe updates (to display the function explicitly)

Instance details

Defined in Tgraph.Force

type UpdateMap = Map Dedge Update Source #

UpdateMap: partial map associating updates with (some) boundary directed edges. (Any boundary directed edge will have the opposite direction in some face.)

newtype UpdateGenerator Source #

UpdateGenerator is a newtype for functions which capture one or more of the forcing rules. The functions can be applied using the unwrapper applyUG and produce a (Try) UpdateMap when given a BoundaryState and a focus list of particular directed boundary edges. Each forcing rule has a particular UpdateGenerator, but they can also be combined (e.g in sequence - allUGenerator or otherwise - defaultAllUGenerator).

Constructors

UpdateGenerator 

type UFinder = BoundaryState -> [Dedge] -> [(Dedge, TileFace)] Source #

UFinder (Update case finder functions). Given a BoundaryState and a list of (focus) boundary directed edges, such a function returns each focus edge satisfying the particular update case paired with the tileface matching that edge. For example, if the function is looking for dart short edges on the boundary, it will return only those focus edges which are half-dart short edges, each paired with its half-dart face.

type UChecker = BoundaryState -> TileFace -> Try Update Source #

UChecker (Update checker functions). Given a BoundaryState and a particular tileface (on the boundary), such functions try to produce particular updates on the boundary edge of the given tileface. [They are called update checkers because they may uncover an incorrect/stuck tiling when creating the update.] As an example, addKiteShortE will try to produce an update to add a half-kite with short edge against the boundary. Such a function can be used with a UFinder that either returns dart halves with short edge on the boundary (nonKDarts in rule 2) or returns kite halves with short edge on the boundary (kitesWingDartOrigin in rule 3).

BoundaryState operations

makeBoundaryState :: Tgraph -> BoundaryState Source #

Calculates BoundaryState information from a Tgraph.

recoverGraph :: BoundaryState -> Tgraph Source #

Converts a BoundaryState back to a Tgraph

facesAtBV :: BoundaryState -> Vertex -> [TileFace] Source #

facesAtBV bd v - returns the faces found at v (which must be a boundary vertex)

boundaryFaces :: BoundaryState -> [TileFace] Source #

return a list of faces which have a boundary vertex from a BoundaryState

Auxiliary Functions for a force step

affectedBoundary :: BoundaryState -> [Dedge] -> [Dedge] Source #

Given a BoundaryState with a list of one boundary edge or two adjacent boundary edges (or exceptionally no boundary edges), it extends the list with adjacent boundary edges (to produce 3 or 4 or none). It will raise an error if given more than 2 or 2 non-adjacent boundary edges. (Used to calculate revisedEdges in a BoundaryChange. (N.B. When a new face is fitted in to a hole with 3 sides there is no new boundary. Hence the need to allow for an empty list.)

tryReviseUpdates :: UpdateGenerator -> BoundaryChange -> UpdateMap -> Try UpdateMap Source #

tryReviseUpdates uGen bdChange: revises the UpdateMap after boundary change (bdChange) using uGen to calculate new updates.

tryReviseFSWith :: UpdateGenerator -> BoundaryChange -> ForceState -> Try ForceState Source #

tryReviseFSWith ugen bdC fs tries to revise fs after a boundary change (bdC) by calculating the revised updates with ugen (and using the new boundary state in bdC).

findSafeUpdate :: UpdateMap -> Maybe Update Source #

finds the first safe update - Nothing if there are none (ordering is directed edge key ordering)

tryUnsafes :: ForceState -> Try (Maybe BoundaryChange) Source #

tryUnsafes: Should only be used when there are no Safe updates in the UpdateMap. tryUnsafes works through the unsafe updates in (directed edge) key order and completes the first unsafe update that is not blocked (by a touching vertex), returning Right (Just bdC) where bdC is the resulting boundary change (if there is one). It returns Right Nothing if there are no unsafe updates but Left report if there are unsafes but all unsafes are blocked, where report describes the problem.

checkUnsafeUpdate :: BoundaryState -> Update -> Maybe BoundaryChange Source #

checkUnsafeUpdate bd u, calculates the resulting boundary change for an unsafe update (u) with a new vertex (raising an error if u is a safe update). It performs a touching vertex check with the new vertex returning Nothing if there is a touching vertex (blocked case). Otherwise it returns Just bdc with bdc a boundary change. [Note: Try is not used as a conflict cannot be found in the unsafe case, and blocking is only a problem when all unsafe updates are blocked (and there is at least one) - see tryUnsafes]

trySafeUpdate :: BoundaryState -> Update -> Try BoundaryChange Source #

trySafeUpdate bd u adds a new face by completing a safe update u on BoundaryState bd (raising an error if u is an unsafe update). It returns a Right BoundaryChange (containing a new BoundaryState, removed boundary edges and revised boundary edge list), unless a stuck/incorrect graph is found. It checks that the new face is not in conflict with existing faces, producing (Left report) if there is a conflict. It should cater for the exceptional case where the update removes 3 boundary edges in a triangle (and removes 3 boundary vertices), closing a hole.

tryUpdate :: BoundaryState -> Update -> Try BoundaryChange Source #

tryUpdate: tries a single update (safe or unsafe), producing Left report if the update creates a touching vertex in the unsafe case, or if a stuck/incorrect Tgraph is discovered in the safe case.

Recalibrating force

recalibratingForce :: Forcible c => c -> c Source #

A version of force that recalibrates at 20,000 step intervals by recalculating boundary vertex positions from scratch. This is needed to limit accumulation of errors when large numbers of faces are added in forcing. This raises an error on discovering a stuck/incorrect Forcible.

tryRecalibratingForce :: Forcible c => c -> Try c Source #

A version of tryForce that recalibrates at 20,000 step intervals by recalculating boundary vertex positions from scratch. This is needed to limit accumulated inaccuracies when large numbers of faces are added in forcing.

recalculateBVLocs :: BoundaryState -> BoundaryState Source #

This recalibrates a BoundaryState by recalculating boundary vertex positions from scratch with locateVertices. (Used at intervals in tryRecalibratingForce and recalibratingForce).

Forcing Rules and Update Generators

FORCING RULES:

  1. (wholeTileUpdates) When a join edge is on the boundary - add the missing half tile to make a whole tile.
  2. (aceKiteUpdates) When a half dart has its short edge on the boundary add the half kite that must be on the short edge (this is at ace vertices but also helps with jack and deuce vertices).
  3. (queenOrKingUpdates) When a vertex is both a dart origin and a kite wing it must be a queen or king vertex. If there is a boundary short edge of a kite half at the vertex, add another kite half sharing the short edge. (This converts 1 kite to 2 and 3 kites to 4 in combination with the first rule).
  4. (deuceDartUpdates) When two half kites share a short edge their oppV vertex must be a deuce vertex. Add any missing half darts needed to complete the vertex.
  5. (jackDartUpdates) When a single dart wing is at a vertex which is recognised as an incomplete jack vertex and has a complete kite below the dart wing, add a second dart half touching at the vertex (sharing the kite below).
  6. (sunStarUpdates) When a vertex has 3 or 4 whole kite origins (= 6 or 8 half kite origins) it must be a sun centre. Also if a vertex has 4 whole dart origins (= 8 half dart origins) it must be a star centre. Add an appropriate half kite/dart on a boundary long edge at the vertex. (This will complete suns (resp. stars) along with rule 1),
  7. (jackKiteUpdates) When a dart half has its wing recognised as a jack vertex add a missing kite half on its long edge.
  8. (kingDartUpdates) When a vertex is a kite wing and also an origin for exactly 4 dart halves it must be a king vertex. Add a missing dart half (on any boundary long edge of a dart at the vertex).
  9. (queenDartUpdates) If there are more than 2 kite wings at a vertex (necessarily a queen) add any missing half dart on a boundary kite long edge. (More than 2 is still valid - was =4)
  10. (queenKiteUpdates) If there are more than 2 kite wings at a vertex (necessarily a queen) add any missing fourth half kite on a boundary kite short edge. (More than 2 rather than =3 to trap false queen case)

There is an update generator for each rule as well as combined update generators (defaultAllUGen, allUGenerator).

The rules are based on the 7 vertex types:

sun, star, jack, queen, king, ace (fool), deuce

Combined Update Generators

defaultAllUGen :: UpdateGenerator Source #

The default all update generator (see also allUGenerator). It uses the 10 rules (and the same UCheckers as allUGenerator), but makes decisions based on the EdgeType of a boundary edge (instead of trying each UFinder in turn). If there are any Left..(fail reports) for the given boundary edges the result is a single Left, concatenating all the failure reports (unlike allUGenerator).

combineUpdateGenerators :: [UpdateGenerator] -> UpdateGenerator Source #

combineUpdateGenerators combines a list of update generators into a single update generator. When used, the generators are tried in order on each boundary edge (in the supplied focus edges), and will return a Left..(fail report) for the first generator that produces a Left..(fail report) if any.

allUGenerator :: UpdateGenerator Source #

allUGenerator was the original generator for all updates. It combines the individual update generators for each of the 10 rules in sequence using combineUpdateGenerators (See also defaultAllUGen which is defined without using combineUpdateGenerators)

Update Generators and Finders for each Rule.

wholeTileUpdates :: UpdateGenerator Source #

Update generator for rule (1)

incompleteHalves :: UFinder Source #

Find faces with missing opposite face (mirror face)

aceKiteUpdates :: UpdateGenerator Source #

Update generator for rule (2)

nonKDarts :: UFinder Source #

Find half darts with boundary short edge

queenOrKingUpdates :: UpdateGenerator Source #

Update generator for rule (3) queen and king vertices add a missing kite half (on a boundary kite short edge)

kitesWingDartOrigin :: UFinder Source #

Find kites with boundary short edge where the wing is also a dart origin

deuceDartUpdates :: UpdateGenerator Source #

Update generator for rule (4) (for deuce vertices = largeKiteCentres) Kites whose short edge (b,a) matches a boundary edge (a,b) where their oppV has 2 other kite halves sharing a shortE. These need a dart adding on the short edge.

kiteGaps :: UFinder Source #

Find kite halves with a short edge on the boundary where there are 2 other kite halves sharing a short edge at oppV of the kite half.

jackDartUpdates :: UpdateGenerator Source #

Update generator for rule (5) jackDartUpdates - jack vertex add a missing second dart

noTouchingDart :: UFinder Source #

Find kite halves with a short edge on the boundary where oppV must be a jack vertex The function mustbeJack finds if a vertex must be a jack.

sunStarUpdates :: UpdateGenerator Source #

Update generator for rule (6) sunStarUpdates is for vertices that must be either sun or star almostSunStar finds half-kites/half-darts with a long edge on the boundary where their origin vertex has 8 total half-kites/half-darts respectively or their origin vertex has 6 total half-kites in the case of kites only completeSunStar will add a new face of the same type (dart/kite) sharing the long edge.

almostSunStar :: UFinder Source #

Find a boundary long edge of either a dart where there are at least 7 dart origins (mustbeStar), or a kite where there are at least 5 kite origins (mustbeSun).

jackKiteUpdates :: UpdateGenerator Source #

Update generator for rule (7) jack vertices with dart long edge on the boundary - add missing kite top. The function mustbeJack finds if a vertex must be a jack.

jackMissingKite :: UFinder Source #

Find a boundary long edge of a dart where the wingV is a jack vertex. The function mustbeJack finds if a vertex must be a jack.

kingDartUpdates :: UpdateGenerator Source #

Update generator for rule (8) king vertices with 2 of the 3 darts - add another half dart on a boundary long edge of existing darts

kingMissingThirdDart :: UFinder Source #

Find a dart long edge on the boundary where the originV must be a king vertex. The function mustbeKing finds if a vertex must be a king (2 of the 3 darts at the origin plus a kite wing at the origin).

queenDartUpdates :: UpdateGenerator Source #

Update generator for rule (9) queen vertices (more than 2 kite wings) with a boundary kite long edge - add a half dart

queenMissingDarts :: UFinder Source #

Find a boundary kite long edge where the wingV must be a queen vertex (more than 2 kite wings at the wingV).

queenKiteUpdates :: UpdateGenerator Source #

Update generator for rule (10) queen vertices with more than 2 kite wings -- add missing half kite on a boundary kite short edge

queenMissingKite :: UFinder Source #

Find a kite short edge on the boundary where the wingV must be a queen vertex (more than 2 kite wings at the wingV).

Six Update Checkers

completeHalf :: UChecker Source #

completeHalf will check an update to add a symmetric (mirror) face for a given face at a boundary join edge.

addKiteShortE :: UChecker Source #

add a (missing) half kite on a (boundary) short edge of a dart or kite

addDartShortE :: UChecker Source #

add a half dart top to a boundary short edge of a half kite.

completeSunStar :: UChecker Source #

add a kite half to a kite long edge or dart half to a dart long edge

addKiteLongE :: UChecker Source #

add a kite to a long edge of a dart or kite

addDartLongE :: UChecker Source #

add a half dart on a boundary long edge of a dart or kite

Boundary vertex properties

mustbeStar :: BoundaryState -> Vertex -> Bool Source #

A vertex on the boundary must be a star if it has 7 or more dart origins

mustbeSun :: BoundaryState -> Vertex -> Bool Source #

A vertex on the boundary must be a sun if it has 5 or more kite origins

mustbeDeuce :: BoundaryState -> Vertex -> Bool Source #

A vertex on the boundary which is an oppV of a kite must be a deuce if there is a shared kite short edge at the vertex.

mustbeKing :: BoundaryState -> Vertex -> Bool Source #

A boundary vertex which is a kite wing and has 4 dart origins must be a king vertex

isKiteWing :: BoundaryState -> Vertex -> Bool Source #

isKiteWing bd v - Vertex v is a kite wing in BoundaryState bd

isKiteOppV :: BoundaryState -> Vertex -> Bool Source #

isKiteOppV bd v - Vertex v is a kite oppV in BoundaryState bd

isDartOrigin :: BoundaryState -> Vertex -> Bool Source #

isDartOrigin bd v - Vertex v is a dart origin in BoundaryState bd

mustbeQueen :: BoundaryState -> Vertex -> Bool Source #

A boundary vertex with >2 kite wings is a queen vertex (needing a fourth kite on a kite short edge or dart on a kite long edge)

kiteWingCount :: BoundaryState -> Vertex -> Int Source #

kiteWingCount bd v - the number of kite wings at v in BoundaryState bd

mustbeJack :: BoundaryState -> Vertex -> Bool Source #

mustbeJack is true of a boundary vertex if it is the wing of two darts not sharing a long edge or it is a wing of a dart and also a kite origin (false means it is either undetermined or is a deuce).

Other tools for making new update generators

newUpdateGenerator :: UChecker -> UFinder -> UpdateGenerator Source #

newUpdateGenerator combines an update case finder (UFinder) with its corresponding update checker (UChecker) to produce an update generator. This is used to make each of the 10 update generators corresponding to 10 rules.

When the generator is applied (with applyUG) to a BoundaryState and list of focus edges, the finder produces a list of pairs of dedge and face, the checker is used to convert the face in each pair to an update (which can fail with a Left report), and the new updates are returned as a map (with the dedges as keys) in a Right result.

boundaryFilter :: (BoundaryState -> Dedge -> TileFace -> Bool) -> UFinder Source #

This is a general purpose filter (previously used to create UFinder functions for each force rule). It requires a face predicate where the face predicate takes a BoundaryState bd, a boundary Dedge (a,b) and the TileFace with the edge (b,a) and decides whether the face is wanted or not (True = wanted) This will be used to filter all the faces at the focus edges (when given a BoundaryState and list of focus edges). For some predicates the BoundaryState argument is not used (eg boundaryJoin in incompleteHalves), but for others it is used to look at other faces at b or at a besides the supplied face (eg in kitesWingDartOrigin)

boundaryEdgeFilter :: EdgeType -> (BoundaryState -> TileFace -> Bool) -> UFinder Source #

This is a general purpose filter used to create UFinder functions for each force rule. It requires an edgeType and a face predicate. The face predicate takes a BoundaryState bd, and a TileFace and (assuming the boundary edge of the face matches the given edgeType) decides whether the face is wanted or not (True = wanted). This will be used to filter all the faces at the focus edges (when given a BoundaryState and list of focus edges). For some predicates the BoundaryState argument is not used (eg boundaryJoin in incompleteHalves), but for others it is used to look at other faces besides the supplied face (eg in kitesWingDartOrigin)

makeUpdate :: (Vertex -> TileFace) -> Maybe Vertex -> Update Source #

makeUpdate f x constructs a safe update if x is Just(..) and an unsafe update if x is Nothing

Auxiliary Functions for adding faces

Note about face additions:

When adding a new face on a boundary edge we need to use some geometric information.

To check if any other edges of the new face are adjacent on the boundary, we calculate external angles at the relevant boundary vertices, using a representation of angles which allows an equality test. (All angles are integer multiples of 1/10th turn (mod 10) so we use these integers for comparing angles n where n is 0..9)

No crossing boundary property: It is important that there are no crossing boundaries to ensure there is a unique external angle at each boundary vertex.

Touching Vertex check: If only one edge of a new face is on the boundary, we need to create a new vertex. This will need to have its position checked against other (boundary) vertices to avoid creating a touching vertex/crossing boundary. This is why BoundaryStates keep track of boundary vertex positions. (The check is done in tryUnsafeUpdate.)

externalAngle :: BoundaryState -> Vertex -> Int Source #

externalAngle bd v - calculates the external angle at boundary vertex v in BoundaryState bd as an integer multiple of tt (tenth turn), so 1..9. It relies on there being no crossing boundaries, so that there is a single external angle at each boundary vertex.

touchCheck :: Point V2 Double -> VertexMap (Point V2 Double) -> Bool Source #

touchCheck p vpMap - check if a vertex location p touches (is too close to) any other vertex location in the mapping vpMap