Skip to content

Commit

Permalink
Adds the North arrow rendering to exported images
Browse files Browse the repository at this point in the history
  • Loading branch information
KnorrFG committed Nov 1, 2020
1 parent 256ed3c commit 734c963
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 12 deletions.
2 changes: 1 addition & 1 deletion session_planner.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ bin = @["session_planner"]

# Dependencies

requires "nim >= 1.4.0", "nigui"
requires "nim >= 1.4.0", "nigui", "optionsutils"
53 changes: 46 additions & 7 deletions src/core.nim
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
import tables, sets, strutils, sequtils
import nigui
import tables, sets, strutils, sequtils, options, sugar
import nigui, optionsutils

type
Point* = tuple[name: string, x, y: float, color: Color]
NormPoint* = tuple[name: string, x, y: int, color: Color]
AbstractPoint*[T] = object
name*: string
x*, y*: T
color*: Color
Point* = AbstractPoint[float64]
NormPoint* = AbstractPoint[int]
Graph* = object
points*: seq[Point]
sessions*: Table[string, HashSet[string]]
Popable*[T] = concept s
s.pop() is T


converter intToFloat64*(i: int): float64 = i.float64


template toFirstClassIter*(it): auto=
iterator iter(): auto {.closure.} =
for x in it:
yield x
iter


template withTemp*(field, tmpVal, code):untyped=
let oldVal = field
field = tmpVal
code
field = oldVal


let
bgColor* = rgb(255, 255, 255)
fgColor* = rgb(0, 0, 0)
Expand Down Expand Up @@ -51,7 +65,32 @@ let
"""


proc normalizePoints*(ps: seq[Point], w, h: float): seq[NormPoint]=
func initPoint*[T](x, y: T, name="", color=colorsTable["schwarz"]):
AbstractPoint[T] = AbstractPoint[T](name:name, x:x, y:y, color:color)


# This could be autogenerated by a macro
func set*[T, T2](p: AbstractPoint[T],
name: string = p.name,
x: T2 = T2(p.x),
y: T2 = T2(p.y),
color: Color = p.color):
AbstractPoint[T2] = AbstractPoint[T2](name:name, x:x, y:y, color:color)


func `+`*[T](p: AbstractPoint[T], offset: (T, T)): AbstractPoint[T]=
p.set(x = p.x + offset[0], y = p.y + offset[1])


func `+`*[T](p: AbstractPoint[T], offset: T): AbstractPoint[T]=
p + (offset, offset)


func `*`*[T](p: AbstractPoint[T], factor: T): AbstractPoint[T]=
p.set(x = p.x * factor, y = p.y * factor)


func normalizePoints*(ps: seq[Point], w, h: float64): seq[NormPoint]=
## Point coordinates are quite large, and assume 0, 0 at the left bottom
## This function recomputes them to be from 0 to (w, h) and the origin at the
## top left
Expand All @@ -60,7 +99,7 @@ proc normalizePoints*(ps: seq[Point], w, h: float): seq[NormPoint]=
return
if ps.len == 1:
let p = ps[0]
return @[(name: p.name, x: int(w / 2), y: int(h / 2), color: p.color)]
return @[initPoint(int(w / 2), int(h / 2), p.name, p.color)]

let
target_w = w * 0.8
Expand All @@ -76,7 +115,7 @@ proc normalizePoints*(ps: seq[Point], w, h: float): seq[NormPoint]=
x_scale = target_w / max_w
y_scale = target_h / max_h
scale = min(x_scale, y_scale)
ps.mapIt((name: it.name,
ps.mapIt(NormPoint(name: it.name,
x: int((it.x - min_x) * scale) + w_offset,
y: int((max_h - (it.y - min_y)) * scale) + h_offset,
color: it.color))
Expand Down
2 changes: 1 addition & 1 deletion src/parser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ proc parsePoints(s: string): seq[Point]=
colorsTable[elems[3]]
else:
raise newException(ParserError, &"Ungültige Farbe: {elems[3]}")
result.add((name: elems[0], x: elems[1].parseFloatOrRaise,
result.add(Point(name: elems[0], x: elems[1].parseFloatOrRaise,
y: elems[2].parseFloatOrRaise, color: color))


Expand Down
32 changes: 29 additions & 3 deletions src/session_planner.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ proc renderToCanvas(points: seq[Point], sessions: iterator: HashSet[string],
canvas.fontFamily = "Arial"

let normPoints = normalizePoints(points,
canvas.width.float,
canvas.height.float).
canvas.width.float64,
canvas.height.float64).
mapIt((it.name, it)).toTable

for p in normPoints.values:
# Coordinates are Pixels, left top is 0, 0
canvas.areaColor = p.color
canvas.drawEllipseArea(p.x, p.y, pointDiameter, pointDiameter)
canvas.drawText(p.name,
p.x - int(0.45 * canvas.getTextWidth(p.name).float),
p.x - int(0.45 * canvas.getTextWidth(p.name).float64),
p.y + canvas.getTextLineHeight())

for s in sessions():
Expand All @@ -34,11 +34,37 @@ proc renderToCanvas(points: seq[Point], sessions: iterator: HashSet[string],
nb.x + pointRadius, nb.y + pointRadius)


proc addNorthArrow(canvas: Canvas)=
## This will add a north arrow to the Graph, as it seems, that niGui does not
## offer any image rotation, or the ability to load an image from memory the
## only way to add a North Arrow, is by manually drawing it
let
(root, head, larm, rarm) = (0, 1, 2, 3)
points = [initPoint(0.0, 1.0),
initPoint(0.0, -1.0),
initPoint(-0.5, -0.5),
initPoint(0.5, -0.5)]
absPoints = collect(newSeq):
for p in points:
(p + (0.5, 1.0)) * 0.02 * canvas.height +
(0.9 * canvas.width, 0.9 * canvas.height)

proc line(start: int, dest: int)=
canvas.drawLine(absPoints[start].x.int, absPoints[start].y.int,
absPoints[dest].x.int, absPoints[dest].y.int)

withTemp(canvas.lineWidth, 2):
line(larm, head)
line(rarm, head)
line(root, head)


proc storeAsImage(state: Graph, savePath: string)=
var img = newImage()
img.resize(1240, 1754)
renderToCanvas state.points, toFirstClassIter state.sessions.values,
img.canvas, rgb(0, 0, 0, 0)
addNorthArrow(img.canvas)
img.saveToPngFile savePath


Expand Down

0 comments on commit 734c963

Please sign in to comment.