【Django】二次関数表示アプリを作成(グラフタイトルの数式を修正し、頂点を表示)[Python]

  • URLをコピーしました!
目次

Django

前回、matplotlibで数式の表示の仕方を解説しました。

今回は前回行ったことをもとに、二次関数グラフ表示アプリの数式を改善していきましょう。

また二次関数では頂点や解が重要になってくるので、その計算式も組み込んでいきます。

ということで今回、最初に修正するファイルは/webapp/quadraticfunction/views.pyです。

そして後で/webapp/quadraticfuction/templates/quadraticfuction/index.html を修正していきます。

webapp
├── bmiapp
│   └── ...
├── db.sqlite3
├── index.cgi
├── linearfunction
│   └── ...
├── manage.py
├── quadraticfunction
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── static
│   │   └── quadraticfunction
│   │       └── quadraticfunction.png
│   ├── templates 
│   │   └── quadraticfunction
│   │       └── index.html           <- 修正
│   ├── tests.py
│   ├── urls.py   
│   └── views.py                     <- 修正
├── static
│   ├── 3pysci_logo.png
│   └── favicon.png
└── webapp
    ├── __init__.py
    ├── asgi.py
    ├── definitions.py
    ├── params.json
    ├── settings.py       
    ├── urls.py                   
    └── wsgi.py

/webapp/quadraticfunction/views.pyのグラフタイトルの数式の修正

前回、matplotlibで数式を表示するには$で囲む、そして上付き数字の場合は「^」を使うということを解説しました。

つまり \(y=ax^2+bx+c\) の場合は「$y=ax^2+bx+c$」とすればいいわけです。

ということで views.py の plotting関数の部分を修正するとこうなります。

def plotting(a, b, c, xmax, xmin, ymax, ymin):

    xlist = range(xmin, xmax+1)

    ylist = []
    for i in xlist:
        ylist.append(a * i * i + b * i + c)

    str_a = checksign(a); str_b = checksign(b); str_c = checksign(c)

    if a == 0:
        if b == 0:
            eq = f'$ y={str_c[0]} $'
        elif b != 0:
            eq = f'$ y={str_b[1]}x{str_c[2]} $'
    elif a != 0:
        if b == 0:
            eq = f'$ y={str_a[1]}x^2{str_c[2]} $'
        elif b != 0:
            eq = f'$ y={str_a[1]}x^2{str_b[3]}x{str_c[2]} $'

    fig = plt.figure()
    plt.clf()

    plt.plot(xlist, ylist)
    plt.grid()
    plt.title(eq,{'fontsize':25})
    plt.xlabel("X", {'fontsize':15})
    plt.ylabel("Y", {'fontsize':15})
    plt.xlim(xmin, xmax)
    plt.ylim(ymin, ymax)

    plt.savefig("./quadraticfunction/static/quadraticfunction/quadraticfunction.png")

aやbの係数で場合分けをし、それぞれの色を変数eqに格納するところで、matplotlibの数式の形にしています。

そしてそれを「plt.title(eq,{‘fontsize’:25})」とすることで、グラフタイトルとして用いています。

ここまでで一度サーバーを起動し、ブラウザで確認してみるとこんな感じです。

/webapp/quadraticfunction/views.pyに頂点と解の計算を追加

次に二次関数の頂点と解の計算を views.py に追加していきます。

ちなみに二次関数の頂点は

(\(-\frac{b}{2a}, -\frac{b^2-4ac}{4a}\))

です。

また解の公式は

\(x=\frac{-b\pm \sqrt{b^2-4ac}}{2a}\)

です。

ということで頂点のX座標、Y座標、解で「+」の時、「ー」の時の4つの数を新たに追加していきます。

またa=0の時やa=0でさらにb=0の時にはこの公式は使えない(二次関数ではないため)ので、その場合わけも必要です。

しかし場合わけに関してもうすでにされているので、それに対して上記4つの値がどのようになるのか追加していくだけになります。

ということでplotting関数はこんな感じになります。

def plotting(a, b, c, xmax, xmin, ymax, ymin):

    xlist = range(xmin, xmax+1)

    ylist = []
    for i in xlist:
        ylist.append(a * i * i + b * i + c)

    str_a = checksign(a); str_b = checksign(b); str_c = checksign(c)

    if a == 0:
        if b == 0:
            eq = f'$ y={str_c[0]} $'
            solution1 = 'なし'
            solution2 = 'なし'
        elif b != 0:
            eq = f'$ y={str_b[1]}x{str_c[2]} $'
            solution1 = str(round(-c/b),2)
            solution2 = 'なし'

        x_vertex = 'なし'
        y_vertex = 'なし'

    elif a != 0:
        if b == 0:
            eq = f'$ y={str_a[1]}x^2{str_c[2]} $'
        elif b != 0:
            eq = f'$ y={str_a[1]}x^2{str_b[3]}x{str_c[2]} $'

        solution1 = str(round((-b + np.sqrt(b * b - 4 * a * c))/(2 * a), 2))
        solution2 = str(round((-b - np.sqrt(b * b - 4 * a * c))/(2 * a), 2))
        x_vertex = str(round(-b/(2 * a), 2))
        y_vertex = str(round(-(b * b - 4 * a * c)/(4 *a), 2))

    fig = plt.figure()
    plt.clf()

    plt.plot(xlist, ylist)
    plt.grid()
    plt.title(eq,{'fontsize':25})
    plt.xlabel("X", {'fontsize':15})
    plt.ylabel("Y", {'fontsize':15})
    plt.xlim(xmin, xmax)
    plt.ylim(ymin, ymax)

    plt.savefig("./quadraticfunction/static/quadraticfunction/quadraticfunction.png")

    return x_vertex, y_vertex, solution1, solution2

頂点のX座標を「x_vertex」、「Y座標をy_vertex」、公式の+の時の解を「solution1」、ーの時の解を「solution2」としました。

そして最後にそれらの値を返すようにしてあります(return x_vertex, y_vertex, solution1, solution2の部分)。

plotting関数で返された値を受け取らなければなりません。

それを修正した最終的なプログラムがこちらです。

from django.shortcuts import render
from django.http import HttpResponse
from .forms import QFForm
import numpy as np
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt
import sys
sys.path.append('../')
from webapp import definitions

def plotting(a, b, c, xmax, xmin, ymax, ymin):

    xlist = range(xmin, xmax+1)

    ylist = []
    for i in xlist:
        ylist.append(a * i * i + b * i + c)

    str_a = checksign(a); str_b = checksign(b); str_c = checksign(c)

    if a == 0:
        if b == 0:
            eq = f'$ y={str_c[0]} $'
            solution1 = 'なし'
            solution2 = 'なし'
        elif b != 0:
            eq = f'$ y={str_b[1]}x{str_c[2]} $'
            solution1 = str(round(-c/b),2)
            solution2 = 'なし'

        x_vertex = 'なし'
        y_vertex = 'なし'

    elif a != 0:
        if b == 0:
            eq = f'$ y={str_a[1]}x^2{str_c[2]} $'
        elif b != 0:
            eq = f'$ y={str_a[1]}x^2{str_b[3]}x{str_c[2]} $'

        solution1 = str(round((-b + np.sqrt(b * b - 4 * a * c))/(2 * a), 2))
        solution2 = str(round((-b - np.sqrt(b * b - 4 * a * c))/(2 * a), 2))
        x_vertex = str(round(-b/(2 * a), 2))
        y_vertex = str(round(-(b * b - 4 * a * c)/(4 *a), 2))

    fig = plt.figure()
    plt.clf()

    plt.plot(xlist, ylist)
    plt.grid()
    plt.title(eq,{'fontsize':25})
    plt.xlabel("X", {'fontsize':15})
    plt.ylabel("Y", {'fontsize':15})
    plt.xlim(xmin, xmax)
    plt.ylim(ymin, ymax)

    plt.savefig("./quadraticfunction/static/quadraticfunction/quadraticfunction.png")

    return x_vertex, y_vertex, solution1, solution2

def checksign(val):
    if val == 0:
        return '0','','',''
    elif val == 1:
        return '1','','+1','+'
    elif val == -1:
        return '-1','-','-1',"-"
    elif val > 0:
        return f'{val}',f'{val}',f'+{val}',f'+{val}'
    elif val < 0:
        return f'{val}',f'{val}',f'{val}',f'{val}'

def index(request):
    params = definitions.readjson()

    initial_val = {
        'a':1,
        'b':0,
        'c':0,
        'xmin':-10,
        'xmax':10,
        'ymin':-10,
        "ymax":10,
    }

    params['forms']= QFForm(request.POST or None, initial=initial_val)

    x_vertex, y_vertex, solution1, solution2 = plotting(initial_val['a'], initial_val['b'],initial_val['c'], initial_val['xmax'], initial_val['xmin'], initial_val['ymax'], initial_val['ymin'])

    params['x_vertex'] = x_vertex
    params['y_vertex'] = y_vertex
    params['solution1'] = solution1
    params['solution2'] = solution2

    if (request.method == 'POST'):
        a = int(request.POST['a'])
        b = int(request.POST['b'])
        c = int(request.POST['c'])
        xmax = int(request.POST['xmax'])
        xmin = int(request.POST['xmin'])
        ymax = int(request.POST['ymax'])
        ymin = int(request.POST['ymin'])

        params['forms'] = QFForm(request.POST)

        x_vertex, y_vertex, solution1, solution2 = plotting(a, b, c, xmax, xmin, ymax, ymin)

        params['x_vertex'] = x_vertex
        params['y_vertex'] = y_vertex
        params['solution1'] = solution1
        params['solution2'] = solution2

    return render(request, 'quadraticfunction/index.html', params)

変更したのは以下の二つの部分です。

    x_vertex, y_vertex, solution1, solution2 = plotting(initial_val['a'], initial_val['b'],initial_val['c'], initial_val['xmax'], initial_val['xmin'], initial_val['ymax'], initial_val['ymin'])
    params['x_vertex'] = x_vertex
    params['y_vertex'] = y_vertex
    params['solution1'] = solution1
    params['solution2'] = solution2
        x_vertex, y_vertex, solution1, solution2 = plotting(a, b, c, xmax, xmin, ymax, ymin)

        params['x_vertex'] = x_vertex
        params['y_vertex'] = y_vertex
        params['solution1'] = solution1
        params['solution2'] = solution2

どちらもplotting関数から戻ってきた値をそれぞれの変数に格納し、さらにparamsに格納しています。

/webapp/quadraticfuction/templates/quadraticfuction/index.html の修正

では次にindex.htmlを修正していきますが、修正後の<!–main–>部分のプログラムはこんな感じです。

        <!-- main -->
        <div class="col-sm-9" style="text-align: center; margin:2rem 0rem 2rem 0rem;">
            <form action="/quadraticfunction/" method="post">
                {% csrf_token %}
                <table style="margin-left:auto; margin-right:auto;">
                <tr><td style="text-align: right;">{{ forms.a.label}}:</td><td>{{ forms.a }}</td><td style="text-align: right;">{{ forms.b.label }}:</td><td>{{ forms.b }}</td><td style="text-align: right;">{{ forms.c.label }}:</td><td>{{ forms.c }}</td></tr>
                <tr><td style="text-align: right;">{{ forms.xmax.label }}:</td><td>{{ forms.xmax }}</td><td style="text-align: right;">{{ forms.xmin.label }}:</td><td>{{ forms.xmin }}</td><td></td></tr>
                <tr><td style="text-align: right;">{{ forms.ymax.label }}:</td><td>{{ forms.ymax }}</td><td style="text-align: right;">{{ forms.ymin.label }}:</td><td>{{ forms.ymin }}</td><td></td></tr>
                <tr><td></td><td></td><td></td><td></td><td></td><td style="text-align: right;"><input type='submit' value="click"></td></tr>
                </table>
            </form>
            <img src="{% static 'quadraticfunction/quadraticfunction.png' %}">
            <p></p>
            <table style="margin-left:auto; margin-right:auto;">
            <tr><td style="text-align: right;"><font size="7">頂点の座標: </font></td><td style="text-align: center;"><font size="7">({{x_vertex}}, {{y_vertex}})</font></td></tr>
            <tr><td style="text-align: right;"><font size="7">解: </font></td><td style="text-align: center;"><font size="7">{{solution1}}, {{solution2}}</font></td></tr>
            </table>
        </div>
        <!-- /main -->

ただ今回追加した部分はこの部分のみです。

            <p></p>
            <table style="margin-left:auto; margin-right:auto;">
            <tr><td style="text-align: right;"><font size="7">頂点の座標: </font></td><td style="text-align: center;"><font size="7">({{x_vertex}}, {{y_vertex}})</font></td></tr>
            <tr><td style="text-align: right;"><font size="7">解: </font></td><td style="text-align: center;"><font size="7">{{solution1}}, {{solution2}}</font></td></tr>
            </table>

グラフ画像の後に先ほどの頂点と解を表示しています。

その際、テーブルを使うことで内容を整列させています。

またテーブル自身も中央寄せしています(<table style=”margin-left:auto; margin-right:auto;”>)。

またデフォルトの文字サイズが結構小さかったので、それぞれ文字に関しては、「<font size=”7″>頂点の座標:</font>」とるすことで文字のサイズを大きくしています。

ちなみにフォントサイズは1から7の7段階で、デフォルトは3です。

あとはそれぞれの文字を場所によって右寄せ(style=”text-align: right;”)や中央寄せ(style=”text-align: center;”)をしています。

これで再度ブラウザで確認してみるとこうなります。

頂点の座標と解が表示されるようになりました。

これで合計3つのWebアプリができたということで、次回からは全部をまとめるウェブサイトのインデックスページを作っていきたいと思います。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次