#31
by かずま » 5年前
反転スコープ さんが書きました: ↑5年前
それと実行するとクリックした瞬間にエラーがでるのですが私の環境だけでしょうか?
コード:
Node &n0 = nodes[i], &n1 = nodes[i - 1];
88行目のここでエラー終了しているようです。
すみません。i = 0 のとき node[i-1] を参照できないからでしょう。
次のように、n1 の宣言を if (i > 0) { の後に移動してください。
コード:
Node &n0 = nodes[i];
DrawCircle(n0.E.x, n0.E.y, 5, color2);
DrawCircle(n0.F.x, n0.F.y, 5, color2);
if (i > 0) {
Node &n1 = nodes[i-1];
vector2 a1, b1, a0, b0, c1, d1;
反転スコープ さんが書きました: ↑5年前
曲線バージョンの方は例の如くまだ理解できていないのですが、これはBスプライン曲線ですか?
曲線バージョンは書いていません。
#19 は、角を落として、短い直線で結んだものです。
#20 は、角の頂点を、短い直線の両端に移したものです。
では、曲線バージョンを次に示します。
でも、曲線というのは嘘で、正十二角形で近似しています。
コード:
#include "DxLib.h"
#include <math.h>
#include <vector>
#define WIDTH 40
using namespace std;
enum { MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE, MOUSE_ALL };
struct Point { double x, y; };
struct Node {
Point P, A, B, C, D, E, F;
vector<Point> arc;
bool turn;
};
int WINAPI WinMain(HINSTANCE hi, HINSTANCE pi, LPSTR cl, int cs)
{
unsigned int mousePressingCount[MOUSE_ALL] = { 0 };
vector<Node> nodes;
int color = GetColor(0, 0, 0);
ChangeWindowMode(TRUE);
SetBackgroundColor(255, 255, 255);
if (DxLib_Init() == -1) return -1;
SetDrawScreen(DX_SCREEN_BACK);
while (!ProcessMessage() && !ScreenFlip() && !ClearDrawScreen()) {
int mouseState = GetMouseInput();
if (mouseState & MOUSE_INPUT_LEFT) mousePressingCount[MOUSE_LEFT]++;
else mousePressingCount[MOUSE_LEFT] = 0;
if (mouseState & MOUSE_INPUT_RIGHT) mousePressingCount[MOUSE_RIGHT]++;
else mousePressingCount[MOUSE_RIGHT] = 0;
if (mouseState & MOUSE_INPUT_MIDDLE) mousePressingCount[MOUSE_MIDDLE]++;
else mousePressingCount[MOUSE_MIDDLE] = 0;
DrawFormatString(0, 0, color, "MouseLeftButton = %d",
mousePressingCount[MOUSE_LEFT]);
DrawFormatString(0, 20, color, "MouseRightButton = %d",
mousePressingCount[MOUSE_RIGHT]);
DrawFormatString(0, 40, color, "MouseMiddleButton = %d",
mousePressingCount[MOUSE_MIDDLE]);
if (mousePressingCount[MOUSE_LEFT] == 1) {
int mouseX, mouseY;
GetMousePoint(&mouseX, &mouseY);
Node node = { (double)mouseX, (double)mouseY, };
nodes.push_back(node);
int n = nodes.size();
if (n >= 2) {
Node &n1 = nodes[n - 1], &n2 = nodes[n - 2];
double dx = n1.P.x - n2.P.x, dy = n1.P.y - n2.P.y;
double dist = sqrt(dx * dx + dy * dy);
double ux = dx / dist * (WIDTH / 2);
double uy = dy / dist * (WIDTH / 2);
n1.A = { n1.P.x - uy, n1.P.y + ux };
n1.B = { n1.P.x + uy, n1.P.y - ux };
n2.C = { n2.P.x - uy, n2.P.y + ux };
n2.D = { n2.P.x + uy, n2.P.y - ux };
if (n == 2) {
n1.E = n1.A, n1.F = n1.B;
n2.A = n2.E = n2.C, n2.B = n2.F = n2.D;
}
else { // n >= 3
n1.E = n1.C = n1.A, n1.F = n1.D = n1.B;
Node &n2 = nodes[n - 2], &n3 = nodes[n - 3];
double x12 = n1.A.x - n2.C.x, y12 = n1.A.y - n2.C.y;
double x32 = n3.C.x - n2.A.x, y32 = n3.C.y - n2.A.y;
double k1 = n2.C.y * x12 - n2.C.x * y12;
double k3 = n2.A.y * x32 - n2.A.x * y32;
double x, y, k = x12 * y32 - x32 * y12;
if (k == 0)
x = n1.C.x, y = n1.C.y;
else {
x = (x32 * k1 - x12 * k3) / k;
y = (y32 * k1 - y12 * k3) / k;
}
n2.E = { x, y };
n2.F = { n2.P.x*2 - x, n2.P.y*2 - y };
n2.turn = (n2.B.y - n2.A.y) * (n2.D.x - n2.C.x) >
(n2.B.x - n2.A.x) * (n2.D.y - n2.C.y);
Point s1, s2;
if (n2.turn)
s1 = n2.A, s2 = n2.C;
else
s1 = n2.B, s2 = n2.D;
const double PI = 3.141592653589793238;
x = s1.x - n2.P.x, y = s1.y - n2.P.y;
double t1 = atan2(y, x);
x = s2.x - n2.P.x, y = s2.y - n2.P.y;
double t2 = atan2(y, x);
if (abs(t2 - t1) > PI)
if (t1 < 0) t1 += 2*PI;
else if (t2 < 0) t2 += 2*PI;
if (t1 > t2) swap(t1, t2), swap(s1, s2);
for (int i = 0; i < 8 && t1 < t2; t1 += PI / 6, i++)
n2.arc.push_back({ WIDTH / 2 * cos(t1) + n2.P.x,
WIDTH / 2 * sin(t1) + n2.P.y });
n2.arc.push_back(s2);
}
}
}
if (mousePressingCount[MOUSE_RIGHT] == 1) nodes.clear();
for (int i = 0; i < nodes.size(); i++) {
int color2 = GetColor(100, 0, 0), color3 = GetColor(224, 128, 0);
Node &n0 = nodes[i];
DrawFormatString(10, i * 20 + 60, color,
"P[%2d] = { %3.0f, %3.0f }", i, n0.P.x, n0.P.y);
DrawCircle(n0.P.x, n0.P.y, 3, color);
if (i > 0) {
Node &n1 = nodes[i-1];
Point a0, b0, a1, b1, c1, d1;
if (n1.turn)
a1 = n1.C, b1 = n1.F, c1 = n1.A, d1 = n1.C;
else
a1 = n1.E, b1 = n1.D, c1 = n1.B, d1 = n1.D;
if (n0.turn)
a0 = n0.A, b0 = n0.F;
else
a0 = n0.E, b0 = n0.B;
DrawLine(a1.x, a1.y, a0.x, a0.y, color3, 2);
DrawLine(b1.x, b1.y, b0.x, b0.y, color3, 2);
int n = n1.arc.size();
for (int i = 1; i < n; i++)
DrawLine(n1.arc[i-1].x, n1.arc[i-1].y,
n1.arc[i].x, n1.arc[i].y, color3, 2);
DrawCircle(a0.x, a0.y, 3, color2);
DrawCircle(b0.x, b0.y, 3, color2);
DrawCircle(a1.x, a1.y, 3, color2);
DrawCircle(b1.x, b1.y, 3, color2);
DrawCircle(c1.x, c1.y, 3, color2);
}
}
}
DxLib_End();
return 0;
}
[quote=反転スコープ post_id=151886 time=1538661116 user_id=2532]
それと実行するとクリックした瞬間にエラーがでるのですが私の環境だけでしょうか?
[code]
Node &n0 = nodes[i], &n1 = nodes[i - 1];
[/code]
88行目のここでエラー終了しているようです。
[/quote]
すみません。i = 0 のとき node[i-1] を参照できないからでしょう。
次のように、n1 の宣言を if (i > 0) { の後に移動してください。
[code]
Node &n0 = nodes[i];
DrawCircle(n0.E.x, n0.E.y, 5, color2);
DrawCircle(n0.F.x, n0.F.y, 5, color2);
if (i > 0) {
Node &n1 = nodes[i-1];
vector2 a1, b1, a0, b0, c1, d1;
[/code]
[quote=反転スコープ post_id=151886 time=1538661116 user_id=2532]
曲線バージョンの方は例の如くまだ理解できていないのですが、これはBスプライン曲線ですか?
[/quote]
曲線バージョンは書いていません。
#19 は、角を落として、短い直線で結んだものです。
#20 は、角の頂点を、短い直線の両端に移したものです。
では、曲線バージョンを次に示します。
でも、曲線というのは嘘で、正十二角形で近似しています。
[code]
#include "DxLib.h"
#include <math.h>
#include <vector>
#define WIDTH 40
using namespace std;
enum { MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE, MOUSE_ALL };
struct Point { double x, y; };
struct Node {
Point P, A, B, C, D, E, F;
vector<Point> arc;
bool turn;
};
int WINAPI WinMain(HINSTANCE hi, HINSTANCE pi, LPSTR cl, int cs)
{
unsigned int mousePressingCount[MOUSE_ALL] = { 0 };
vector<Node> nodes;
int color = GetColor(0, 0, 0);
ChangeWindowMode(TRUE);
SetBackgroundColor(255, 255, 255);
if (DxLib_Init() == -1) return -1;
SetDrawScreen(DX_SCREEN_BACK);
while (!ProcessMessage() && !ScreenFlip() && !ClearDrawScreen()) {
int mouseState = GetMouseInput();
if (mouseState & MOUSE_INPUT_LEFT) mousePressingCount[MOUSE_LEFT]++;
else mousePressingCount[MOUSE_LEFT] = 0;
if (mouseState & MOUSE_INPUT_RIGHT) mousePressingCount[MOUSE_RIGHT]++;
else mousePressingCount[MOUSE_RIGHT] = 0;
if (mouseState & MOUSE_INPUT_MIDDLE) mousePressingCount[MOUSE_MIDDLE]++;
else mousePressingCount[MOUSE_MIDDLE] = 0;
DrawFormatString(0, 0, color, "MouseLeftButton = %d",
mousePressingCount[MOUSE_LEFT]);
DrawFormatString(0, 20, color, "MouseRightButton = %d",
mousePressingCount[MOUSE_RIGHT]);
DrawFormatString(0, 40, color, "MouseMiddleButton = %d",
mousePressingCount[MOUSE_MIDDLE]);
if (mousePressingCount[MOUSE_LEFT] == 1) {
int mouseX, mouseY;
GetMousePoint(&mouseX, &mouseY);
Node node = { (double)mouseX, (double)mouseY, };
nodes.push_back(node);
int n = nodes.size();
if (n >= 2) {
Node &n1 = nodes[n - 1], &n2 = nodes[n - 2];
double dx = n1.P.x - n2.P.x, dy = n1.P.y - n2.P.y;
double dist = sqrt(dx * dx + dy * dy);
double ux = dx / dist * (WIDTH / 2);
double uy = dy / dist * (WIDTH / 2);
n1.A = { n1.P.x - uy, n1.P.y + ux };
n1.B = { n1.P.x + uy, n1.P.y - ux };
n2.C = { n2.P.x - uy, n2.P.y + ux };
n2.D = { n2.P.x + uy, n2.P.y - ux };
if (n == 2) {
n1.E = n1.A, n1.F = n1.B;
n2.A = n2.E = n2.C, n2.B = n2.F = n2.D;
}
else { // n >= 3
n1.E = n1.C = n1.A, n1.F = n1.D = n1.B;
Node &n2 = nodes[n - 2], &n3 = nodes[n - 3];
double x12 = n1.A.x - n2.C.x, y12 = n1.A.y - n2.C.y;
double x32 = n3.C.x - n2.A.x, y32 = n3.C.y - n2.A.y;
double k1 = n2.C.y * x12 - n2.C.x * y12;
double k3 = n2.A.y * x32 - n2.A.x * y32;
double x, y, k = x12 * y32 - x32 * y12;
if (k == 0)
x = n1.C.x, y = n1.C.y;
else {
x = (x32 * k1 - x12 * k3) / k;
y = (y32 * k1 - y12 * k3) / k;
}
n2.E = { x, y };
n2.F = { n2.P.x*2 - x, n2.P.y*2 - y };
n2.turn = (n2.B.y - n2.A.y) * (n2.D.x - n2.C.x) >
(n2.B.x - n2.A.x) * (n2.D.y - n2.C.y);
Point s1, s2;
if (n2.turn)
s1 = n2.A, s2 = n2.C;
else
s1 = n2.B, s2 = n2.D;
const double PI = 3.141592653589793238;
x = s1.x - n2.P.x, y = s1.y - n2.P.y;
double t1 = atan2(y, x);
x = s2.x - n2.P.x, y = s2.y - n2.P.y;
double t2 = atan2(y, x);
if (abs(t2 - t1) > PI)
if (t1 < 0) t1 += 2*PI;
else if (t2 < 0) t2 += 2*PI;
if (t1 > t2) swap(t1, t2), swap(s1, s2);
for (int i = 0; i < 8 && t1 < t2; t1 += PI / 6, i++)
n2.arc.push_back({ WIDTH / 2 * cos(t1) + n2.P.x,
WIDTH / 2 * sin(t1) + n2.P.y });
n2.arc.push_back(s2);
}
}
}
if (mousePressingCount[MOUSE_RIGHT] == 1) nodes.clear();
for (int i = 0; i < nodes.size(); i++) {
int color2 = GetColor(100, 0, 0), color3 = GetColor(224, 128, 0);
Node &n0 = nodes[i];
DrawFormatString(10, i * 20 + 60, color,
"P[%2d] = { %3.0f, %3.0f }", i, n0.P.x, n0.P.y);
DrawCircle(n0.P.x, n0.P.y, 3, color);
if (i > 0) {
Node &n1 = nodes[i-1];
Point a0, b0, a1, b1, c1, d1;
if (n1.turn)
a1 = n1.C, b1 = n1.F, c1 = n1.A, d1 = n1.C;
else
a1 = n1.E, b1 = n1.D, c1 = n1.B, d1 = n1.D;
if (n0.turn)
a0 = n0.A, b0 = n0.F;
else
a0 = n0.E, b0 = n0.B;
DrawLine(a1.x, a1.y, a0.x, a0.y, color3, 2);
DrawLine(b1.x, b1.y, b0.x, b0.y, color3, 2);
int n = n1.arc.size();
for (int i = 1; i < n; i++)
DrawLine(n1.arc[i-1].x, n1.arc[i-1].y,
n1.arc[i].x, n1.arc[i].y, color3, 2);
DrawCircle(a0.x, a0.y, 3, color2);
DrawCircle(b0.x, b0.y, 3, color2);
DrawCircle(a1.x, a1.y, 3, color2);
DrawCircle(b1.x, b1.y, 3, color2);
DrawCircle(c1.x, c1.y, 3, color2);
}
}
}
DxLib_End();
return 0;
}
[/code]