主にゲーム用のリアルタイムなアニメーション補間のために
0<=x<=1の範囲でf(0)=0,f(1)=1となり、斜め軸(y=1-x)で線対称になる式がほしいです
条件は
y=1-x上の通過点を1点指定し、
A(0,0)で傾き真上、(1,1)で傾き真右、の場合
B(0,0)で傾き真右、(1,1)で傾き真上、の場合
の2パターンの式がほしいです
画像を添付しておきます
また、計算速度に関する問題や妥協点などあれば教えていただけると助かります
(円の方程式に指数を与えるとかなり近いのですが、内側に変化させられないため断念しました)
C++での実装を想定しています
よろしくお願いいたします
追記です
図では紫のグラフ(条件A)の点を掴んでいますが、これがy=xをまたぐ際に緑(条件B)の方に切り替えて使用します
またアニメーション用途のため、xは時間を表していて線形変化を緩急のある変化に変えるために使います
(例としてスケール初期値100%~終端200%として線形ではなくいきなり180%くらいまでデカくなったのちゆっくりに落ち着くといった動きなどを表現)
そのためyの範囲は0~1で収まるものを想定しています
S字型のカーブをさせるための情報は
http://marupeke296.com/TIPS_No19_interpolation.html
が参考になったのですが今回のお椀型?の仕様に合う情報が欲しいです
更に追記
下記コードにて出力した点をプロットしたものが下記画像となります
a=0.1(緑)
a=0.25(赤)
a=0.4(水)
これが傾きの要件をみたしているのかはわからないのですが、これを線形補間で使えばもう十分かな感はあります
ただ、ソースのコメントにあるように分割時の右半分のYを求める係数がわからないため中央付近が異常に荒くなっています
struct f2 { float m_x; float m_y; }; f2 outf2[20]; int numout=0; void saiki(int div, f2 v0, f2 v1, float a) { if(div){ float sax = v1.m_x - v0.m_x;//差x float say = v1.m_y - v0.m_y;//差y f2 center_vec; center_vec.m_x = v0.m_x + sax*0.5f; //xは中間 center_vec.m_y = v0.m_y + say*(1.f-a); //yは1-aでブレンド saiki(div-1, v0, center_vec, a);//左半分の再帰呼び出し outf2[numout++] = center_vec; //motomu(div-1, center_vec, v1, a);//右側分割が上手く行かない } else{ return; } } void func() { float a = 0.25f;//掴んでいる点のx座標 f2 v0 = {0.f, 0.f};//原点 f2 v1 = {a, 1.f-a};//y=x上の点 saiki(5, v0, v1, a); outf2[numout++] = v1; //ここで出したoutf2は半分だけなのであとは手作業で鏡面写し }
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
下記のような質問は推奨されていません。
- 質問になっていない投稿
- スパムや攻撃的な表現を用いた投稿
適切な質問に修正を依頼しましょう。
回答7件
3
ベストアンサー
円の方程式の指数部を変えればいいので、その考え方に基づいてやるとすれば式としては
abs(y) = (1 - (abs(x-1))^n)^(1/n)
abs(y-1) = (1 - (abs(x))^n)^(1/n)
でしょう。nの値の大小で曲がり具合を変更できます。こちらのサイトとかで、1<=n<100くらいで試してみてください(小数可)。
この方法はp-ノルムの考え方に基づきます。
円のように4象限分は要らないので、絶対値を外して必要な部分だけ切り出して、
-y+1 = (1 - x^n)^(1/n)→y=-(1 - x^n)^(1/n) + 1
y = (1 - (-x+1)^n)^(1/n)
とかで良さそうです。xからyを計算したい場合はこちらを使います。
見慣れた円の方程式のような形に変形すると、
x^n + (-y+1)^n = 1
(-x+1)^n + y^n = 1
です。
制御点を通る曲線に対応するnの計算方法ですが、制御点はy = 1-x上にあるので、これを代入すると、
x^n = 1/2
y^n = 1/2
ですから、log_x 0.5とlog_y 0.5(x, yを底とする対数)を計算すれば必要なnが求まります。
式を分けないで、どっちかの式にn=log_x 0.5とlog_y 0.5を与えればy=xに対して線対称の2曲線が得られるはずです。
(この場合、(x, y)=(0.8, 0.2)なら約3.11と約0.43とかになると思います)
(これで行ける理由はなんとなくわかるようなわからないような感じなので、あとで説明を思いついたら追記しておきます)
(か、どなたかコメントで書いていただけると助かります)
投稿2021/05/26 05:23
編集2021/05/26 08:14総合スコア30913
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
2021/05/26 06:14
2
傾きの条件を無視してよくて、かつ、「斜め軸(y=1-x)で線対称になる」が譲歩できる(ちょっと違ってもいい)のなら、ガンマ補正カーブの式を使うとか
(99) OpenCV #4 : ガンマ補正で画像を見やすく調整
y=xの直線に対する対称性は、ガンマ値を逆数にします (たとえば、ガンマ=2とガンマ=1/2がy=xに対して対称)
ただし、曲線の形のコントロールは、式上では点の座標ではなくガンマ値になります
曲線がここ通ってほしい点の座標からlog関数でガンマ値を計算して曲線の式を決めたら、任意のxに対するyを計算できます
投稿2021/05/26 01:48
編集2021/05/26 02:02総合スコア7597
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
2021/05/26 02:39 編集
1
こんなのどうでしょうか?
python
1import numpy as np 2import matplotlib.pyplot as plt 3 4# xは0.0と1.0は含まないようにする 5dx = 0.001 6x = np.arange(dx, 1.0, dx) 7 8# 曲線を通したい点からaを計算 9xx = 0.4 10yy = 1 - xx 11a = 1 - (1 - yy) / (yy * (1 / xx - 1)) 12 13# 曲線 (aで形が変わる) 14y1 = 1 / (1 + (1 / x - 1) * (1 - a)) 15y2 = -1 / (1 + x / (1 - x) * (1 - a)) + 1 16 17plt.plot(x, y1, x, y2) 18plt.axis('square') 19plt.show()
【追記】 計算式を下記のように変えたら、x=0.0, 1.0も計算できます
python
1# 曲線 (aで形が変わる) 2y1 = x / (x + (1 - x) * (1 - a)) 3y2 = -1 * (1 - x) / ((1 - x) + x * (1 - a)) + 1
投稿2021/05/26 06:13
編集2021/05/26 07:19総合スコア7597
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
2021/05/30 15:46
1
関数というと計算するものだと考えていらっしゃるかもしれませんが、データを表で持っておいて、その表を引いて補間すれば、実用的には十分です。
c51d4802ecc4f6fa31d0a2da7ccf16db.pngのグラフのデータをもう少し細かい間隔で作っておき、xとyを入れ替えたものを多少いじれば右下の関数の表も作成できます。
一個の関数を表す表は64要素ぐらい作っておけば十分ではないですか。それだとdoubleで持っても512バイトですね。変化量を128通り持っても64キロバイトです。
そうやって作った表をC/C++の配列データとして書き出してリンクしておけば、実行時には表引き+補間で計算できるので、計算コストは最小限で済みます。
投稿2021/05/26 04:08
総合スコア24641
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
2021/05/26 04:11
2021/05/26 05:03
2021/05/26 05:12 編集
1
端点の傾きは妥協して,
放物線 f(x) = a*x*x + b*x
で,
左下の点(0,0) と,制御点 (x,1-x) までを結ぶ曲線を表すことを考えました.
制御点の座標が与えられた際に,
- 制御点を通る
- 制御点での傾き = 1
という条件の下で,aとbの値を解いてやります.
下図は制御点の x座標 = 0.3 での例です.
青いのが求めた放物線で,赤いのがそれを直線 y=1-x を境に反転したものです.
この2本の曲線を,x=0.3を境に繋いでやれば,一本の曲線になります.
こんなのじゃダメですかね?
投稿2021/05/26 03:38
編集2021/05/26 03:39総合スコア10905
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
2021/05/26 00:50
2021/05/26 02:34
1
スプライン曲線でよいのではないでしょうか.
この条件だと,こんな感じの弓っぽい形になっちゃうかも?
妥協点
妥協して良い所なのかどうかは不明ですが,
両端の傾きを妥協するならば,適当な(三角関数とか放物線とか,何かしらの)山なりな形の曲線を45度回転すれば良い気がしますが…
投稿2021/05/25 09:21
編集2021/05/25 10:45総合スコア10905
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
関連した質問
Q&A
解決済
Animatorで現在再生中のステートをハイライトしてほしい
回答1
クリップ0
更新
2023/05/31
Q&A
解決済
Rのggplot2で作図したグラフを拡張メタファイル(.emf)として余白無く出力したい
回答2
クリップ0
更新
2023/06/01
Q&A
受付中
ページリロード時にページ上部から表示させたい
回答1
クリップ0
更新
2023/06/01
Q&A
解決済
CSSで、hover時にボタンの背景をスライド式に変えたい
回答2
クリップ0
更新
2023/05/25
Q&A
解決済
CSS position: absolute が効きません
回答1
クリップ0
更新
2023/05/23
Q&A
受付中
c++でアニメーション描画
回答2
クリップ0
更新
2023/06/01
Q&A
解決済
エフェクトを追加したボタンアイコンのリンク機能がちゃんと作動するようにしたい。
回答1
クリップ0
更新
2023/05/24
Q&A
解決済
GoogleMapsAPIで最初に表示されるズームレベルをパラメータで指定する方法
回答1
クリップ1
更新
2023/05/31