dive statistics wish list

Lubomir I. Ivanov neolit123 at gmail.com
Wed Mar 16 11:37:58 PDT 2016


On 15 March 2016 at 21:28, Willem Ferguson
<willemferguson at zoology.up.ac.za> wrote:
> A graphs that I would personally like to see is a scatter diagram depicting
> SAC against dive depth. I find that my SAC increases with depth, so a
> graphical representation of SAC with depth could actually help with dive
> planning if SAC is one of the parameters going into the planning. The way
> that I would use this is to select a subset of dives from the dive list and
> do this graph for that subset.

here is a homebrew, POC scatter plotter in QML / JS using Context2D in 100 LOC.

lubomir
--
-------------- next part --------------
import QtQuick 2.0
import QtQuick.Window 2.2

Window {
	width: 480
	height: 800
	visible: true
	title: "scatter"

	Canvas {
		id: canvas
		anchors.fill: parent

		function paintAxises(ctx, w, h, pad, grid, labelx, labely, min_x, min_y, max_x, max_y)
		{
			var lw = 4;
			ctx.strokeStyle = Qt.rgba(0, 0, 0, 1);
			ctx.lineWidth = lw;
			ctx.beginPath();
			ctx.moveTo(pad, h - pad);
			ctx.lineTo(w - pad, h - pad);
			ctx.moveTo(pad, h - pad);
			ctx.lineTo(pad, pad);
			ctx.stroke();
			ctx.beginPath();
			ctx.lineWidth = lw / 2;
			var grid_offset = lw * 2;
			var grid_perx = Math.round((w - pad * 2) / grid);
			var grid_pery = Math.round((h - pad * 2) / grid);
			var i;
			for (i = 0; i < grid_perx; i++) {
				ctx.moveTo(pad + grid * i, h - pad - grid_offset);
				ctx.lineTo(pad + grid * i, h - pad + grid_offset);
			}
			for (i = 0; i < grid_pery; i++) {
				ctx.moveTo(pad - grid_offset, h - pad - grid * i);
				ctx.lineTo(pad + grid_offset, h - pad - grid * i);
			}
			ctx.stroke();
			var font_height = 12;
			var pad_label = 25;
			ctx.font = "bold " + font_height + "px sans-serif";
			ctx.fillStyle = Qt.rgba(0, 0, 1.0, 1);
			ctx.fillText(labelx, pad + (w - pad * 2 - ctx.measureText(labelx).width) / 2, h - pad + font_height + pad_label);
			ctx.fillText(labely, pad - ctx.measureText(labely).width - pad_label, pad + (h - pad * 2) / 2);

			var font_height = 10;
			var pad_step = 10;
			ctx.font = font_height + "px sans-serif";
			ctx.fillStyle = Qt.rgba(0, 0, 0, 1);
			var stepx = min_x + Math.round(max_x / grid_perx);
			var stepy = min_y + Math.round(max_y / grid_pery);
			var step_text;
			for (i = 1; i < grid_perx; i++) {
				step_text = i * stepx;
				ctx.fillText(step_text, pad + grid * i - ctx.measureText(step_text).width / 2, h - pad + font_height + pad_step);
			}
			for (i = 1; i < grid_pery; i++) {
				step_text = i * stepy;
				ctx.fillText(step_text, pad - ctx.measureText(step_text).width - pad_step, h - pad - grid * i + font_height / 2);
			}
		}

		function paintGrid(ctx, w, h, pad, grid)
		{
			ctx.strokeStyle = Qt.rgba(0, 0, 0, 0.2);
			ctx.lineWidth = 1;
			ctx.beginPath();
			var i;
			for (i = 0; i < (w - pad * 2) / grid; i++) {
				ctx.moveTo(pad + grid * i, h - pad);
				ctx.lineTo(pad + grid * i, pad);
			}
			for (i = 0; i < (h - pad * 2) / grid; i++) {
				ctx.moveTo(pad, h - pad - grid * i);
				ctx.lineTo(w - pad, h - pad - grid * i);
			}
			ctx.stroke();
		}

		function paintScatterElement(ctx, w, h, x, y)
		{
			ctx.beginPath();
			ctx.arc(x, y, 10, 0, 2*Math.PI);
			ctx.fillStyle = Qt.rgba(x / w, y / h, 0, 0.5);
			ctx.fill();
			ctx.stroke();
		}

		function paintScatter(ctx, pad, w, h, data)
		{
			ctx.strokeStyle = Qt.rgba(0, 0, 0, 1);
			w -= pad * 2;
			h -= pad * 2;
			ctx.lineWidth = 1;
			for (var i = 0; i < data.length; i++) {
				var x = data[i][0] + pad;
				var y = data[i][1] + pad;
				paintScatterElement(ctx, w, h, x, y);
			}
		}

		onPaint: {
			var w = canvas.width;
			var h = canvas.height;
			var pad = 100;
			var grid = 40;
			var ctx = getContext("2d");
			paintAxises(ctx, w, h, pad, grid, "SAC", "DEPTH (m)", 0, 0, 20, 100);
			paintGrid(ctx, w, h, pad, grid);

			var data = [];
			var data_pad = 40;
			for (var i = 0; i < 100; i++) {
				var x = data_pad + Math.random() * (w - pad * 2 - data_pad * 2);
				var y = data_pad + Math.random() * (h - pad * 2 - data_pad * 2);
				data.push([x, y]);
			}
			paintScatter(ctx, pad, w, h, data);
		}
	}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: scatter.png
Type: image/png
Size: 78917 bytes
Desc: not available
URL: <http://lists.subsurface-divelog.org/pipermail/subsurface/attachments/20160316/d6aa9d8f/attachment-0001.png>


More information about the subsurface mailing list