16 | module CyBy.Draw.Internal.DoubleBond
18 | import Derive.Prelude
19 | import Data.Graph.Indexed.Query.BFS
20 | import CyBy.Draw.Internal.Atom
21 | import CyBy.Draw.Internal.CoreDims
22 | import CyBy.Draw.Internal.Graph
23 | import CyBy.Draw.Internal.Label
28 | %language ElabReflection
36 | data RingSize : Type where
38 | Ring : (multibonds, size : Nat) -> RingSize
39 | Hexane : (multibonds : Nat) -> RingSize
41 | %runElab derive "RingSize" [Eq,Ord]
52 | -> (Point Id, Point Id)
53 | parallelLine r b x y =
54 | (perpendicularPoint x y r b, perpendicularPoint y x r $
not b)
59 | ParallelDistance : (cd : CoreDims) => Double
60 | ParallelDistance = 0.8 * cd.radiusAtom
64 | HalfParallelDistance : (cd : CoreDims) => Double
65 | HalfParallelDistance = 0.5 * ParallelDistance
69 | parameters {auto cd : CoreDims}
73 | (ox,oy,px,py : Point Id)
75 | countMBs : Nat -> List (Fin k) -> Nat
76 | countMBs n (a::t@(b::_)) =
77 | case (type . molBond) <$> elab g a b of
78 | Just Dbl => countMBs (S n) t
79 | Just Triple => countMBs (S n) t
83 | ringSize : (nx,ny : Fin k) -> RingSize
85 | case limitedBfs g [x,y] nx ny of
88 | let path := x :: (sn <>> [y])
89 | mbs := countMBs 0 path
90 | in case length path of
94 | displace : Vector Id
95 | displace = scaleTo (tan (pi / 6) * ParallelDistance) (oy - ox)
98 | dx = if ox == px then translate displace ox else px
101 | dy = if oy == py then translate (negate displace) oy else py
103 | deflt : Vect 4 (Point Id)
105 | let (v,w) := parallelLine HalfParallelDistance True px py
106 | (x,y) := parallelLine HalfParallelDistance False px py
109 | notXorY : Fin k -> Bool
110 | notXorY n = n /= x && n /= y
112 | leftOfY : Angle -> Fin k -> Bool
114 | let Just chi := angle (pointAt g n - px) | Nothing => False
115 | in chi - phi <= Angle.pi
117 | dominantNode : Fin k -> Vect 4 (Point Id)
119 | let Just phi := angle (py - px) | Nothing => deflt
120 | (v,w) := parallelLine ParallelDistance (leftOfY phi n) dx dy
124 | dblBond : Vect 4 (Point Id)
126 | case (filter (y /=) (neighbours g x), filter (x /=) (neighbours g y)) of
127 | ([nx1,nx2],[ny1,ny2]) =>
128 | let r1 := max (ringSize nx1 ny1) (ringSize nx2 ny1)
129 | r2 := max (ringSize nx1 ny2) (ringSize nx2 ny2)
130 | in if r1 >= r2 then dominantNode ny1 else dominantNode ny2
131 | ([_,_],[ny]) => dominantNode ny
132 | ([nx], [_,_]) => dominantNode nx
133 | ([nx], [_]) => dominantNode nx