2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

plotly.js で陰関数を描画する

Last updated at Posted at 2020-04-12

概要

意外と検索してもヒットしなかったので、記事にまとめます。
大まかに言うと、等高線のplotをします。

やりたいこと

今回は $y^2 = x^3 - 4 x$ が描きたいグラフです。
$f(x,y) = x^3 - 4 x - y^2$ に対して、 $|f(x,y)| \le \epsilon$ を満たす点を描画します。

結果の例

結果はこんな感じです。

epsilon=0.1
ゼロの近傍を $-0.1 \le f(x,y) \le 0.1$ とした場合のグラフです。
image.png

epsilon=1.0
やっていることが分かりにくいので、ゼロの近傍を $-10 \le f(x,y) \le 10$ までに広げたものです。

image.png

方針

陰関数が描きたいというのに、等高線で我慢すれば良いんじゃね?と思ったのですが、見たいもの以外の情報が入りすぎるので情報を削ります。

  • 楽するためには絶対値を取ります
    • $f(x,y)$ は、ゼロをまたぐところで符号が変わります。
    • 符号が変わると、 contour で描く等高線は別の色になります。
    • 正負で同じ色をつける colorscale はなさそうです。それに、colorscaleをカスタマイズするのは面倒です。
  • colorscale の z_maxepsilon を合わせます
    • $x^3$ のオーダーですし、スケールが広ければ広いほど 0 周辺が目立たなくなります。そうなると本末転倒ですから、カラーバーの目盛りを 0 ~ epsilon までの範囲に制限します。

JavaScriptのコード例

function window_function(z, epsilon) {
    positive_z = Math.abs(z);
    if (positive_z > epsilon) return epsilon;
    return positive_z;
}

let cd_ary_x = [];
let cd_ary_y = [];
let cd_ary_z = [];

let x_min = -5;
let x_max = 5;
let x_sample_size = 600;
let dx = (x_max - x_min) / x_sample_size;

let y_min = -5;
let y_max = 5;
let y_sample_size = 600;
let dy = (y_max - y_min) / y_sample_size;

let epsilon = 0.1;

for (let x = x_min; x <= x_max; x += dx) {
  for (let y = y_min; y <= y_max; y += dy) {
    cd_ary_x.push(x);
    cd_ary_y.push(y);
    cd_ary_z.push(window_function(x*x*x - 4 * x - y * y, epsilon));
  }
}

var cd_trace = {
  color:'rgb(0,0,0)',
  x: cd_ary_x,
  y: cd_ary_y,
  z: cd_ary_z,
  type: 'contour',
  colorscale: 'Hot',
  z_min: 0,
  z_max: epsilon
};

var cd_layout = {
    hovermode:'closest',
    autosize: false, width: 600, height: 600,
    yaxis: { l: 10, r: 10, b: 10, t: 10, pad: 4 },
    paper_bgcolor: '#efefef'
};
Plotly.newPlot('jacobi_elliptic_functions_plot_area', [cd_trace], cd_layout, {displayModeBar: false});

呼び出し元のコード

今回は AsciiDoc に埋め込んだのでこんな感じです。

ifndef::leveloffset[]
:toc: left
:toclevels: 3

ifeval::["{backend}" == "html5"]
pass:[<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>]
endif::[]

endif::[]

include::header.adoc[]

== Jacobi elliptic functions

ifeval::["{backend}" == "html5"]
**楕円関数: f(_x_) = _x_^3^ -4__x__ - _y_^2^**
[pass]
++++
<div id="jacobi_elliptic_functions_plot_area"><!-- Plotly chart will be drawn inside this DIV --></div>
<script>
include::js/jacobi_elliptic_functions.js[]
</script>
++++
endif::[]

htmlで試したい人のために、htmlに仕立て上げたものも参考に載せます。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Pragma" content="no-cache">
<meta charset="utf-8">
<script type="text/javascript" src="https://cdn.plot.ly/plotly-latest.min.js" charset="utf-8"></script>
<title>Jacobi elliptic functions</title>
</head>

<body>

<div id="jacobi_elliptic_functions_plot_area"></div>
<script language="JavaScript" type="text/javascript">
function window_function(z, epsilon) {
    positive_z = Math.abs(z);
    if (positive_z > epsilon) return epsilon;
    return positive_z;
}

let cd_ary_x = [];
let cd_ary_y = [];
let cd_ary_z = [];

let x_min = -5;
let x_max = 5;
let x_sample_size = 600;
let dx = (x_max - x_min) / x_sample_size;

let y_min = -5;
let y_max = 5;
let y_sample_size = 600;
let dy = (y_max - y_min) / y_sample_size;

let epsilon = 0.2;

for (let x = x_min; x <= x_max; x += dx) {
  for (let y = y_min; y <= y_max; y += dy) {
    cd_ary_x.push(x);
    cd_ary_y.push(y);
    cd_ary_z.push(window_function(x*x*x - 4 * x - y * y, epsilon));
  }
}

var cd_trace = {
  color:'rgb(0,0,0)',
  x: cd_ary_x,
  y: cd_ary_y,
  z: cd_ary_z,
  type: 'contour',
  colorscale: 'Hot',
  z_min: 0,
  z_max: epsilon
};

var cd_layout = {
    hovermode:'closest',
    autosize: false, width: 600, height: 600,
    yaxis: { l: 10, r: 10, b: 10, t: 10, pad: 4 },
    paper_bgcolor: '#efefef'
};
Plotly.newPlot('jacobi_elliptic_functions_plot_area', [cd_trace], cd_layout, {displayModeBar: false});
</script>

</body>
</html>

参考

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?