Skip to content

Commit

Permalink
Fixed incorrect size of shapes crossing DST changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
goat1000 committed Nov 18, 2021
1 parent ac540e2 commit 5cf590b
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 33 deletions.
11 changes: 11 additions & 0 deletions Axis.php
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,17 @@ public function uneven()
return $this->uneven;
}

/**
* Returns the distance in pixels $u takes from $pos
*/
public function measureUnits($pos, $u)
{
// on an ordinary axis this works fine
$l = $this->position($u);
$zero = $this->position(0);
return $l - $zero;
}

/**
* Returns the position of a value on the axis
*/
Expand Down
43 changes: 43 additions & 0 deletions AxisDateTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,49 @@ private static function endTime($time, $unit, $n, $start)
return $datetime;
}

/**
* Returns the distance in pixels $u takes from $pos
*/
public function measureUnits($pos, $u)
{
$i = Coords::parseValue($pos);

// start with a plain date
$datetime = new \DateTime('@0');
$datetime->setTimezone($this->timezone);
if($i['simple']) {
$a = new Number($pos);
$datetime = new \DateTime('@' . $a);
$datetime->setTimezone($this->timezone);
} elseif($i['grid']) {
if($i['units']) {
list($units, $unit_count) = AxisDateTime::parseFixedDivisions($i['value'],
$this->start, $this->end, $this->length);
$datetime->setTimezone($this->timezone);
$uc = new Number($unit_count);
$datetime->modify('+' . $uc . ' ' . $units);
} else {
$v = Graph::dateConvert($i['value']);
$a = new Number($v);
$datetime = new \DateTime('@' . $a);
$datetime->setTimezone($this->timezone);
}
}

$start_value = $datetime->format('U');
$start_pos = $this->length * ($start_value - $this->start) / $this->duration;

list($units, $unit_count) = AxisDateTime::parseFixedDivisions($u,
$this->start, $this->end, $this->length);

$datetime->setTimezone($this->timezone);
$uc = new Number($unit_count);
$datetime->modify('+' . $uc . ' ' . $units);
$value = $datetime->format('U');
$end_pos = $this->length * ($value - $this->start) / $this->duration;
return $end_pos - $start_pos;
}

/**
* Returns the position of a value on the axis
*/
Expand Down
13 changes: 12 additions & 1 deletion AxisLog.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Copyright (C) 2013-2020 Graham Breach
* Copyright (C) 2013-2021 Graham Breach
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand Down Expand Up @@ -153,6 +153,17 @@ public function getGridSubdivisions($min_space, $min_unit, $start, $fixed)
return $points;
}

/**
* Returns the distance in pixels $u takes from $pos
*/
public function measureUnits($pos, $u)
{
$i = Coords::parseValue($pos);
$start_pos = $this->position($i['value']);
$end_pos = $this->position($i['value'] + $u);
return $end_pos - $start_pos;
}

/**
* Returns the position of a value on the axis, or NULL if the position is
* not possible
Expand Down
8 changes: 8 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
Version 3.11 (18/11/2021)
------------
- Added exploded donut graph.
- Added donut_slice_gap option.
- Fixed problem in datetime axis labelling around DST changes.
- Fixed incorrect shape sizes on datetime graph around DST changes.
- Fixed positioning of axis labels on datetime bar graphs.

Version 3.10 (19/07/2021)
------------
- Added support for using text as a shape or figure.
Expand Down
3 changes: 2 additions & 1 deletion Circle.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Copyright (C) 2019 Graham Breach
* Copyright (C) 2019-2021 Graham Breach
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand All @@ -25,6 +25,7 @@ class Circle extends Shape {
protected $element = 'circle';
protected $required = ['cx','cy','r'];
protected $transform = ['r' => 'y'];
protected $transform_from = ['r' => 'cy'];
protected $transform_pairs = [ ['cx', 'cy'] ];
}

64 changes: 40 additions & 24 deletions Coords.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Copyright (C) 2015-2019 Graham Breach
* Copyright (C) 2015-2021 Graham Breach
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand Down Expand Up @@ -52,7 +52,7 @@ public function isGrid($x, $y)
/**
* splits $value, removing leading char and updating $axis, $axis_no
*/
private function valueAxis(&$value, &$axis, &$axis_no)
private static function valueAxis(&$value, &$axis, &$axis_no)
{
if(preg_match('/^[ug](.*?)(([xy])(\d?))?$/i', $value, $matches)) {
$value = $matches[1];
Expand All @@ -79,56 +79,72 @@ public function transformCoords($x, $y)
}

/**
* Transform from grid space etc. to SVG space
* Determines the type of value
*/
public function transform($value, $axis, $default_pos = 0)
public static function parseValue($value, $axis = null)
{
$info = [
'value' => $value, 'axis' => $axis, 'axis_no' => null,
'simple' => true, 'grid' => false, 'units' => false
];
if(is_numeric($value) || !is_string($value))
return $value;
$first = strtolower(substr($value, 0, 1));
$grid = false;
return $info;

$info['simple'] = false;
$first = strtolower(substr($value, 0, 1));
if($first == 'u' || $first == 'g') {
if(!method_exists($this->graph, 'gridX'))
throw new \Exception('Invalid dimensions (non-grid graph)');
Coords::valueAxis($value, $axis, $axis_no);
$info['value'] = $value;
$info['axis'] = $axis;
$info['axis_no'] = $axis_no;
$info['grid'] = true;
$info['units'] = ($first == 'u');
}
return $info;
}

$this->valueAxis($value, $axis, $axis_no);
/**
* Transform from grid space etc. to SVG space
*/
public function transform($value, $axis, $default_pos = 0, $measure_from = 0)
{
$v_info = Coords::parseValue($value, $axis);
if($v_info['simple'])
return $value;

if($first == 'u') {
// value is in grid units
$func = $axis == 'x' ? 'unitsX' : 'unitsY';
return $this->graph->{$func}($value, $axis_no) -
$this->graph->{$func}(0, $axis_no);
}
$value = $v_info['value'];
if($v_info['grid'] && !method_exists($this->graph, 'gridX'))
throw new \Exception('Invalid dimensions (non-grid graph)');

// value is a grid position
$grid = true;
if($v_info['units']) {
$axis_inst = $this->graph->getAxis($v_info['axis'], $v_info['axis_no']);
return $axis_inst->measureUnits($measure_from, $value);
}

$dim = $this->graph->getDimensions();

// try value as assoc/datetime key first
if($grid) {
$axis_inst = $this->graph->getAxis($axis, $axis_no);
if($v_info['grid']) {
$axis_inst = $this->graph->getAxis($v_info['axis'], $v_info['axis_no']);
$position = $axis_inst->positionByKey($value);
if($position !== null) {
if($axis == 'x')
if($v_info['axis'] == 'x')
return $position + $dim['pad_left'];
return $dim['height'] - $dim['pad_bottom'] - $position;
}
}

if(is_numeric($value)) {
if($grid) {
if($v_info['grid']) {
$func = $axis == 'x' ? 'gridX' : 'gridY';
return $this->graph->{$func}($value, $axis_no);
return $this->graph->{$func}($value, $v_info['axis_no']);
}
return $value;
}

if($value == 'c')
$value .= $axis;
if($grid)
if($v_info['grid'])
return $this->getGridPosition($value, $default_pos);
return $this->getGraphPosition($value, $default_pos);
}
Expand Down
3 changes: 2 additions & 1 deletion Ellipse.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Copyright (C) 2019 Graham Breach
* Copyright (C) 2019-2021 Graham Breach
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand All @@ -25,6 +25,7 @@ class Ellipse extends Shape {
protected $element = 'ellipse';
protected $required = ['cx','cy','rx','ry'];
protected $transform = ['rx' => 'x', 'ry' => 'y'];
protected $transform_from = ['rx' => 'cx', 'ry' => 'cy'];
protected $transform_pairs = [ ['cx', 'cy'] ];
}

3 changes: 2 additions & 1 deletion Image.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Copyright (C) 2019 Graham Breach
* Copyright (C) 2019-2021 Graham Breach
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand All @@ -25,6 +25,7 @@ class Image extends Shape {
protected $element = 'image';
protected $required = ['src', 'x', 'y'];
protected $transform = ['width' => 'x', 'height' => 'y'];
protected $transform_from = ['width' => 'x', 'height' => 'y'];
protected $transform_pairs = [ ['x', 'y'] ];
protected $attrs = ['preserveAspectRatio' => 'xMinYMin'];

Expand Down
3 changes: 2 additions & 1 deletion MarkerShape.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Copyright (C) 2019 Graham Breach
* Copyright (C) 2019-2021 Graham Breach
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand All @@ -25,6 +25,7 @@ class MarkerShape extends Shape {
protected $element = 'use';
protected $required = ['type', 'x', 'y'];
protected $transform = ['size' => 'y'];
protected $transform_from = ['size' => 'y'];
protected $transform_pairs = [ ['x', 'y'] ];

/**
Expand Down
4 changes: 3 additions & 1 deletion README.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SVGGraph Library version 3.10
SVGGraph Library version 3.11
=============================

This library provides PHP classes and functions for easily creating SVG
Expand Down Expand Up @@ -90,6 +90,8 @@ At the moment these types of graph are supported by SVGGraph:

SemiDonutGraph - half of a donut graph;

ExplodedDonutGraph - a donut graph with its slices exploded;

PolarAreaGraph - a pie graph where the area of the slice varies instead of
its angle;

Expand Down
3 changes: 2 additions & 1 deletion Rect.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Copyright (C) 2019 Graham Breach
* Copyright (C) 2019-2021 Graham Breach
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand All @@ -25,6 +25,7 @@ class Rect extends Shape {
protected $element = 'rect';
protected $required = ['x','y','width','height'];
protected $transform = ['width' => 'x', 'height' => 'y'];
protected $transform_from = ['width' => 'x', 'height' => 'y'];
protected $transform_pairs = [ ['x', 'y'] ];
}

2 changes: 1 addition & 1 deletion SVGGraph.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class SVGGraph {

use SVGGraphTrait;

const VERSION = 'SVGGraph 3.10';
const VERSION = 'SVGGraph 3.11';
private $width = 100;
private $height = 100;
private $settings = [];
Expand Down
12 changes: 11 additions & 1 deletion Shape.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ abstract class Shape {
*/
protected $transform = [];

/**
* map attributes to be transformed to the attribute they are relative to
* - 'attr_relative' => 'attr_fixed'
*/
protected $transform_from = [];

/**
* coordinate pairs for dependent transforns - don't include them in
* $transform or they will be transformed twice
Expand Down Expand Up @@ -119,7 +125,11 @@ public function draw(&$graph)
if($value !== null) {
$val = $value;
if(isset($this->transform[$attr])) {
$val = $this->coords->transform($value, $this->transform[$attr]);
$measure_from = 0;
if(isset($this->transform_from[$attr]))
$measure_from = $this->attrs[$this->transform_from[$attr]];

$val = $this->coords->transform($value, $this->transform[$attr], 0, $measure_from);
} elseif(isset($this->colour_convert[$attr])) {
$val = new Colour($graph, $value, $this->colour_convert[$attr]);
}
Expand Down

0 comments on commit 5cf590b

Please sign in to comment.