Browse Source

Start adding hermite interpolation

pull/38/head
Florian Mounier 11 years ago
parent
commit
c5b296096e
  1. 2
      demo/moulinrouge/tests.py
  2. 4
      pygal/graph/graph.py
  3. 32
      pygal/interpolate.py

2
demo/moulinrouge/tests.py

@ -159,7 +159,7 @@ def get_test_routes(app):
@app.route('/test/interpolate/<chart>') @app.route('/test/interpolate/<chart>')
def test_interpolate_for(chart): def test_interpolate_for(chart):
graph = CHARTS_BY_NAME[chart](interpolate='cubic') graph = CHARTS_BY_NAME[chart](interpolate='hermite')
graph.add('1', [1, 3, 12, 3, 4]) graph.add('1', [1, 3, 12, 3, 4])
graph.add('2', [7, -4, 10, None, 8, 3, 1]) graph.add('2', [7, -4, 10, None, 8, 3, 1])
return graph.render_response() return graph.render_response()

4
pygal/graph/graph.py

@ -23,7 +23,7 @@ Commmon graphing functions
from __future__ import division from __future__ import division
from pygal.interpolate import ( from pygal.interpolate import (
quadratic_interpolate, cubic_interpolate) quadratic_interpolate, cubic_interpolate, hermite_interpolate)
from pygal.graph.base import BaseGraph from pygal.graph.base import BaseGraph
from pygal.view import View, LogView, XYLogView from pygal.view import View, LogView, XYLogView
from pygal.util import ( from pygal.util import (
@ -388,6 +388,8 @@ class Graph(BaseGraph):
interpolate = cubic_interpolate interpolate = cubic_interpolate
if self.interpolate == 'quadratic': if self.interpolate == 'quadratic':
interpolate = quadratic_interpolate interpolate = quadratic_interpolate
elif self.interpolate == 'hermite':
interpolate = hermite_interpolate
return list(interpolate(x, y, self.interpolation_precision)) return list(interpolate(x, y, self.interpolation_precision))

32
pygal/interpolate.py

@ -92,6 +92,38 @@ def cubic_interpolate(x, y, precision=250):
yield x[i] + X, a[i] + b[i] * X + c[i] * X2 + d[i] * X3 yield x[i] + X, a[i] + b[i] * X + c[i] * X2 + d[i] * X3
def hermite_interpolate(x, y, precision=250):
n = len(x) - 1
m = [1] * (n + 1)
c = 0
delta_x = [x2 - x1 for x1, x2 in zip(x, x[1:])]
for i in range(1, n):
m[i] = (1 - c) * (y[i + 1] - y[i - 1]) / (x[i + 1] - x[i - 1])
def p(i, x_):
t = (x_ - x[i]) / delta_x[i]
t2 = t * t
t3 = t2 * t
h00 = 2 * t3 - 3 * t2 + 1
h10 = t3 - 2 * t2 + t
h01 = - 2 * t3 + 3 * t2
h11 = t3 - t2
return (h00 * y[i] +
h10 * m[i] * delta_x[i] +
h01 * y[i + 1] +
h11 * m[i + 1] * delta_x[i])
for i in range(n + 1):
yield x[i], y[i]
if i == n or delta_x[i] == 0:
continue
for s in range(1, precision):
X = x[i] + s * delta_x[i] / precision
yield X, p(i, X)
if __name__ == '__main__': if __name__ == '__main__':
from pygal import XY from pygal import XY
points = [(.1, 7), (.3, -4), (.6, 10), (.9, 8), (1.4, 3), (1.7, 1)] points = [(.1, 7), (.3, -4), (.6, 10), (.9, 8), (1.4, 3), (1.7, 1)]

Loading…
Cancel
Save