From 445a976f2e6f67d6e7db5ab4d85dd8b1b38a8be4 Mon Sep 17 00:00:00 2001 From: Nathan McRae Date: Sat, 19 Jul 2025 22:47:34 -0700 Subject: [PATCH] Get primary function compiling --- src/Main.purs | 81 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/src/Main.purs b/src/Main.purs index c16457f..19b5bba 100644 --- a/src/Main.purs +++ b/src/Main.purs @@ -1,16 +1,15 @@ module Main where -import Prelude (discard, class Monoid, class Semigroup, Unit, ($), (<>), (>>>), (*), (+), (-), (/)) +import Prelude (discard, class Monoid, class Semigroup, Unit, ($), (<<<), (<>), (*), (+), (-), (/)) -import Data.Array (range, cons) -import Data.Field (div) +import Data.Array (range, concat, mapWithIndex) import Data.Functor (map) import Data.Int (toNumber) import Data.Number (cos, pi, sin) import Data.Number.Format (toString) import Data.List (fold) import Data.Ord ((<)) -import Data.Ring (add, mul, negate, sub) +import Data.Ring (negate) import Data.Tuple.Nested (Tuple3, tuple3, get1, get2, get3) import Effect (Effect) import Effect.Console (log) @@ -69,6 +68,11 @@ svgLine { start: {x: x1, y: y1}, end: {x: x2, y: y2} } = XMLFragment $ """ (toString x1) <> "," <> (toString y1) <> " " <> (toString x2) <> "," <> (toString y2) <> "\"/>" +svgText :: String -> Number -> Point -> Number -> XMLFragment +svgText text fontSize { x: x, y: y } angle = + XMLFragment $ " (toString fontSize) <> "\"px;line-height:131%;font-family:'Liberation sans';font-variant-position:super;fill:#000000;stroke:#000000;stroke-width:0.0999998;stroke-linecap:round;stop-color:#000000;fill-opacity:1\" " + <> "transform=\"translate(" <> (toString x) <> ", " <> (toString y) <> ") rotate(" <> (toString angle) <> ")\">" <> text <> "" + -- TODO: Make axis tick size a parameter getTick :: Number -> Int -> Int -> Line getTick scale numTicks tickI = @@ -105,27 +109,56 @@ ternaryGraphSvg fragments = """ xmlns:svg="http://www.w3.org/2000/svg"> """ <> unfragment (fold fragments) <> "" -axesPoints :: Number -> Array Point -axesPoints angle = [ - rotate angle { x: 0.0, y: 1.0 }, - rotate angle { x: -(sin (2.0 * pi / 3.0)), y : -0.5}, - rotate angle { x: (sin (2.8 * pi / 3.0)), y: -0.5 } -] +axesPoints :: Number -> Tuple3 Point Point Point +axesPoints angle = tuple3 + (rotate angle { x: 0.0, y: 1.0 }) + (rotate angle { x: -(sin (2.0 * pi / 3.0)), y : -0.5}) + (rotate angle { x: (sin (2.8 * pi / 3.0)), y: -0.5 }) ---ternaryGraph :: Number -> Number -> Number -> Int -> String ---ternaryGraph scale xOffset yOffset numTicks = ternaryGraphSvg [tickLinesSvg, axesPathSvg, axisTitleSvg, tickLabelsSvg] --- where --- axisTickLines = getTicks scale pi numTicks --- axis1TickLines = get1 axisTickLines --- axis2TickLines = get2 axisTickLines --- axis3TickLines = get3 axisTickLines --- tickLines = (cons axis1TickLines (cons axis2TickLines axis3TickLines)) --- transformMyLine = transformLine scale xOffset yOffset --- tickLinesSvg = fold $ map (svgLine >>> transformMyLine) tickLines --- --- axesPathSvg = +axesPath :: Point -> Point -> Point -> XMLFragment +axesPath p1 p2 p3 = XMLFragment $ """ "d=\"M " <> (toString p1.x) <> "," <> (toString p1.y) <> " " <> (toString p2.x) <> "," <> (toString p2.y) <> " " <> (toString p3.x) <> "," <> (toString p3.y) <> " Z\"/>" + +ternaryGraph :: Number -> Number -> Number -> Int -> String +ternaryGraph scale xOffset yOffset numTicks = ternaryGraphSvg fragments + where + axisTickLines = getTicks scale pi numTicks + axis1TickLines = get1 axisTickLines + axis2TickLines = get2 axisTickLines + axis3TickLines = get3 axisTickLines + tickLines = concat [axis1TickLines, axis2TickLines, axis3TickLines] -- (cons axis1TickLines (cons axis2TickLines [axis3TickLines)) + transformMyLine = transformLine scale xOffset yOffset + tickLinesSvg = fold $ map (svgLine <<< transformMyLine) tickLines + + axesPointsPi = axesPoints pi + axesPathSvg = axesPath (get1 axesPointsPi) (get2 axesPointsPi) (get3 axesPointsPi) + + -- TODO: axis text size + axisTitlesSvg = [ + svgText "axis 1" 1.0 (transform scale xOffset yOffset {x: 0.0, y: 1.2}) 0.0, + svgText "axis 2" 1.0 (transform scale xOffset yOffset {x: -(sin (2.0 * pi / 3.0)), y: -0.7}) (-60.0), + svgText "axis 3" 1.0 (transform scale xOffset yOffset {x: (sin (2.8 * pi / 3.0)), y: -0.7}) 60.0 + ] + + axisTickStarts = map (\line -> transform scale xOffset yOffset line.start) + -- TODO: tick label size + -- TODO: axis tick label rotation + -- TODO: axis tick start number + axisTickLabels = \rotation -> mapWithIndex (\i point -> svgText ("E" <> (toString (toNumber i))) 1.0 point 0.0) + + axis1TickLabels = axisTickLabels 0 $ axisTickStarts axis1TickLines + axis2TickLabels = axisTickLabels 0 $ axisTickStarts axis2TickLines + axis3TickLabels = axisTickLabels 0 $ axisTickStarts axis3TickLines + + tickLabelsSvg = concat [ + axis1TickLabels, + axis2TickLabels, + axis3TickLabels + ] + + fragments = concat [[tickLinesSvg, axesPathSvg], axisTitlesSvg, tickLabelsSvg] main :: Effect Unit main = do - log $ ternaryGraphSvg [XMLFragment "", XMLFragment ""] - log $ toString $ toNumber (5 / 3) + log $ ternaryGraph 100.0 50.0 50.0 10 + log $ toString $ toNumber (5 / 3) \ No newline at end of file