1#
2# canvas.draw library - compass rose module
3# created 12/2018 by jsb
4# WARNING: this is still under development, interfaces may change
5#
6
7var CompassRose = {
8    VERSION: 1.0,
9    Style: {
10        new: func() {
11            var obj = {
12                parents: [CompassRose.Style, canvas.draw.marksStyle.new()],
13                mark_count: 36,       # number of marks, count = 360 / interval
14                label_count: 12,      # number of text labels (degrees)
15                label_div: 10,        # >0 div. degr. by this for text labels
16                circle_color: [255,255,255,1],
17                mark_color:   [255,255,255,1],
18                label_color:  [255,255,255,1],
19                center_mark: 0,       # draw a mark in the center of the rose
20                font: "sans",         # fontsize for labels
21                font_weight: "bold",  # fontsize for labels
22                fontsize: 0,          # fontsize for labels
23                nesw: 1,              # replace labels 0,90,180,270 by N,E,S,W
24            };
25            obj.setMarkLength(0.1);
26            obj.setSubdivisionLength(0.5);
27            return obj;
28        },
29
30        setMarkCount: func(value) {
31            me.mark_count = num(value) or 0;
32            return me;
33        },
34
35        setLabelCount: func(value) {
36            me.label_count = num(value) or 0;
37            return me;
38        },
39
40        # divide course by this value before creating text label. (try 10, 1 or 0)
41        setLabelDivisor: func(value) {
42            me.label_div = num(value) or 10;
43            return me;
44        },
45
46        setFontSize: func(value) {
47            me.fontsize = num(value) or 26;
48            return me;
49        },
50    },
51};
52
53# draw a compass rose
54# cgroup    canvas group, marks and lables will be created as children
55CompassRose.draw = func(cgroup, radius, style=nil) {
56    if (style == nil) {
57        style = me.Style.new();
58    }
59    cgroup = cgroup.createChild("group", "compass-rose");
60    if (style.center_mark) {
61        var center = cgroup.createChild("path","center");
62        var l = radius * 0.1;
63        center.setStrokeLineWidth(1).setColor(style.circle_color)
64            .moveTo(-l,0).line(2*l,0).moveTo(0,-l).line(0,2*l);
65    }
66    if (style.baseline_width > 0) {
67        var c = cgroup.createChild("path", "circle");
68        c.circle(radius)
69         .setStrokeLineWidth(style.baseline_width)
70         .setColor(style.circle_color);
71    }
72    if (style.mark_count > 0) {
73        var marks = canvas.draw.marksCircular(cgroup, radius, 360 / style.mark_count, 0, 360, style);
74        marks.setStrokeLineWidth(style.mark_width);
75    }
76    var fontsize = style.fontsize;
77    if (style.fontsize == 0) {
78        fontsize = math.round(math.sqrt(radius) * 1.4);
79    }
80    if (style.label_count > 0) {
81        var labels = cgroup.createChild("group", "labels")
82            .createChildren("text", style.label_count);
83        var offset = (style.mark_offset < 0 ? -1 : 1) * style.mark_length * radius;
84        var rot = 2*math.pi/style.label_count;
85        var font = canvas.font_mapper(style.font, style.font_weight);
86        forindex (i; labels) {
87            var t = n = int(i*360 / style.label_count);
88            if (style.label_div > 0) t = int(n / style.label_div);
89            var txt = sprintf("%d", t);
90            if (style.nesw) {
91                if (n == 0) txt = "N";
92                elsif (n == 90) txt = "E";
93                elsif (n == 180) txt = "S";
94                elsif (n == 270) txt = "W";
95            }
96            labels[i]
97                .setText(txt)
98                .setFontSize(fontsize)
99                .setFont(font)
100                .setColor(style.label_color)
101                .setAlignment("center-"~(style.mark_offset < 0 ? "top" : "bottom"))
102                .setTranslation(0,-radius-offset)
103                .setCenter(0,radius+offset)
104                .setRotation(i*rot);
105        }
106    }
107    return cgroup;
108};
109