mirror of
https://github.com/rgleichman/glance.git
synced 2024-08-16 18:30:36 +03:00
Flip diagrams when that results in shorter line distances.
This commit is contained in:
parent
97c84d27e5
commit
0985291c80
18
app/Main.hs
18
app/Main.hs
@ -18,7 +18,12 @@ import Icons
|
||||
import Rendering
|
||||
|
||||
-- todo: Find out how to hide unqualified names such that recursive drawings are connected correctly
|
||||
-- todo: Flip and rotate the icons after placement to minimize line distances to ports.
|
||||
-- todo: Rotate based on difference from ideal tangent angle, not line distance.
|
||||
-- todo: layout and rotate considering external connections.
|
||||
-- todo: add port to bottom of guard.
|
||||
-- todo: give GraphViz square or circular icons such that rotation can not cause icons to inersect.
|
||||
-- todo: use constants for icon name strings in Main
|
||||
-- todo: figure out local vs. global icon positions
|
||||
|
||||
applyDia = apply0Dia
|
||||
-- --apply0A = "A" .>> applyDia
|
||||
@ -127,7 +132,8 @@ factIcons = toNames
|
||||
("recurAp", Apply0Icon),
|
||||
("*Ap1", Apply0Icon),
|
||||
("*Ap2", Apply0Icon),
|
||||
("arg", BranchIcon)
|
||||
("arg", BranchIcon),
|
||||
("res", ResultIcon)
|
||||
]
|
||||
|
||||
factEdges = [
|
||||
@ -138,10 +144,12 @@ factEdges = [
|
||||
iconToPort "one" "g0" 2,
|
||||
portToPort "*Ap2" 2 "g0" 4,
|
||||
portToPort "*Ap1" 2 "*Ap2" 0,
|
||||
portToPort "recurAp" 2 "*Ap1" 3,
|
||||
iconToPort "arg" "eq0Ap" 3,
|
||||
portToPort "recurAp" 2 "*Ap1" 1,
|
||||
iconToPort "arg" "eq0Ap" 1,
|
||||
iconToPort "arg" "-1Ap" 1,
|
||||
iconToPort "arg" "*Ap2" 1
|
||||
iconToPort "arg" "*Ap2" 1,
|
||||
portToPort "-1Ap" 2 "recurAp" 1,
|
||||
iconToPort "res" "g0" 0
|
||||
]
|
||||
|
||||
factDrawing = Drawing factIcons factEdges []
|
||||
|
@ -82,7 +82,8 @@ totalLenghtOfLines angle myLocation edges = sum $ map edgeDist edges
|
||||
where
|
||||
--edgeDist :: (P2 a, P2 a) -> Double
|
||||
edgeDist (relativePortLocation, iconLocation) =
|
||||
(norm $ absPortVec ^-^ iconLocationVec)
|
||||
-- The squaring here is arbitrary. Distance should be replaced with angle diff.
|
||||
(norm $ absPortVec ^-^ iconLocationVec) ** 2
|
||||
where
|
||||
-- todo: is there a better way to convert from Points to vectors?
|
||||
relPortVec = r2 $ unp2 relativePortLocation
|
||||
@ -90,12 +91,17 @@ totalLenghtOfLines angle myLocation edges = sum $ map edgeDist edges
|
||||
myLocVec = r2 $ unp2 myLocation
|
||||
absPortVec = myLocVec ^+^ (rotateBy angle relPortVec)
|
||||
|
||||
angleWithMinDist :: P2 Double -> [(P2 Double, P2 Double)] -> Double
|
||||
-- | returns (angle, total distance)
|
||||
angleWithMinDist :: P2 Double -> [(P2 Double, P2 Double)] -> (Double, Double)
|
||||
angleWithMinDist myLocation edges =
|
||||
fst $ minimumBy (compare `on` snd) $ map totalLength [0,(1/40)..1]
|
||||
minimumBy (compare `on` snd) $ map totalLength [0,(1/40)..1]
|
||||
where
|
||||
totalLength angle = (angle, totalLenghtOfLines angle myLocation edges)
|
||||
|
||||
-- constant
|
||||
scaleFactor = 0.025
|
||||
|
||||
getFromMapAndScale posMap name = scaleFactor *^ (posMap ! name)
|
||||
|
||||
-- | rotateNodes rotates the nodes such that the distance of its connecting lines
|
||||
-- are minimized.
|
||||
@ -103,29 +109,36 @@ angleWithMinDist myLocation edges =
|
||||
-- todo: confirm precondition (or use a newtype)
|
||||
rotateNodes positionMap nameDiagramMap edges = map rotateDiagram nameDiagramMap
|
||||
where
|
||||
rotateDiagram (name, dia) = (name, rotateBy minAngle dia)
|
||||
rotateDiagram (name, dia) = (name, diaToUse)
|
||||
where
|
||||
flippedDia = reflectX dia
|
||||
(unflippedAngle, unflippedDist) = minAngleForDia dia
|
||||
(flippedAngle, flippedDist) = minAngleForDia flippedDia
|
||||
diaToUse = if flippedDist < unflippedDist
|
||||
then rotateBy flippedAngle flippedDia
|
||||
else rotateBy unflippedAngle dia
|
||||
minAngleForDia :: Diagram B -> (Double, Double)
|
||||
minAngleForDia dia = minAngle where
|
||||
--ports = Debug.Trace.trace ((show $ names dia) ++ "\n") $ names dia
|
||||
ports = names dia
|
||||
namesOfPortsWithLines = connectedPorts edges name
|
||||
portEdges = map makePortEdge $ filter iconInMap namesOfPortsWithLines
|
||||
iconInMap (_, otherIconName, _) = Map.member otherIconName positionMap
|
||||
makePortEdge (portInt, otherIconName, _) = (getPortPoint portInt, positionMap ! otherIconName)
|
||||
getPortPoint :: Int -> P2 Double
|
||||
getPortPoint x = head $ fromMaybe
|
||||
(error "port not found")
|
||||
(lookup (name .> x) ports)
|
||||
minAngle = angleWithMinDist (positionMap ! name) portEdges
|
||||
ports = names dia
|
||||
namesOfPortsWithLines = connectedPorts edges name
|
||||
portEdges = map makePortEdge $ filter iconInMap namesOfPortsWithLines
|
||||
iconInMap (_, otherIconName, _) = Map.member otherIconName positionMap
|
||||
makePortEdge (portInt, otherIconName, _) = (getPortPoint portInt, getFromMapAndScale positionMap otherIconName)
|
||||
getPortPoint :: Int -> P2 Double
|
||||
getPortPoint x = head $ fromMaybe
|
||||
(error "port not found")
|
||||
(lookup (name .> x) ports)
|
||||
minAngle = angleWithMinDist (getFromMapAndScale positionMap name) portEdges
|
||||
|
||||
placeNodes layoutResult nameDiagramMap edges = mconcat placedNodes
|
||||
where
|
||||
(positionMap, _) = getGraph layoutResult
|
||||
rotatedNameDiagramMap = rotateNodes positionMap nameDiagramMap edges
|
||||
placedNodes = map placeNode rotatedNameDiagramMap
|
||||
--placedNodes = map placeNode nameDiagramMap
|
||||
-- todo: Not sure if the diagrams should already be centered at this point.
|
||||
placeNode (name, diagram) = place (diagram # centerXY) (scaleFactor *^ (positionMap ! name))
|
||||
-- constant
|
||||
scaleFactor = 0.025
|
||||
|
||||
doGraphLayout graph nameDiagramMap connectNodes edges = do
|
||||
layoutResult <- layoutGraph' layoutParams Neato graph
|
||||
|
Loading…
Reference in New Issue
Block a user