一定の太さで線を引く簡単な方法を作りました。これが私の機能です:
void ColoringScene::drawThickLine(int x1, int y1, int x2, int y2, int r, int g, int b, int a, float wd, bool began, unsigned char* data, unsigned char* areasData){
if(began){
//if just began draw "dot" with filled circle
drawFilledCircle(x1, y1, 1, wd, r, g, b, a, data, areasData);
return;
}
//otherwise calculate angle between two points
int angle = (int)(atan2(-y2 + y1, x2 - x1) * 180 / M_PI);
int a1 = angle - 90;
int a2 = angle + 90;
//calculate a distance between two points
float diff = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
if(diff > wd) diff = wd;
//find all points in arc from angle - 90 to angle + 90
for(float _r = a1; _r < a2; _r+=1.0f){
float _x1 = cos(CC_DEGREES_TO_RADIANS(_r)) * wd + x1;
float _y1 = -sin(CC_DEGREES_TO_RADIANS(_r)) * wd + y1;
float _x2 = cos(CC_DEGREES_TO_RADIANS(_r)) * wd + x2;
float _y2 = -sin(CC_DEGREES_TO_RADIANS(_r)) * wd + y2;
//connect point from 2 arcs with line
drawLine(floor(_x1), floor(_y1), floor(_x2), floor(_y2), r, g, b, a, data, areasData);
}
}
(x1, y1) から (x2, y2) に色 (r, g, b, a) と太さ wd で線を引く必要があります。画面上で指を動かしながら描画するときにこのメソッドを使用するので、追加のパラメーター「began」も追加しました。これは、タッチが開始したか、タッチが移動したかを示します。データはピクセルの配列です。エリアデータは関係ありません。
しかし、期待どおりに機能していません。結果の例を次に示します。
少し圧縮されている可能性がありますが、細かく描かれた 2 つの点と、穴のある多くの「太い」線から曲線が構築されていることがわかります。
「wd」が十分に大きくない場合、問題は存在しません。精度に何らかの問題があることはほぼ確実です。
私は試しました: - for ループを 0 から 360 に変更します (角度-90、角度 + 90 ではありません)。- floor の代わりに round を使用 - -sin の代わりに sin を使用 (私の場合、y はいずれにせよ反転されます) - 0.05 のように 1.0 より低い _r を使用します。
また、指定された固定の太さ (この例では 60 ピクセル) では、_r 増分や角度などのパラメーターを設定して、穴なしで描画しないようにする方法はありません。
これを行うために独自の関数を作成することにしました。これは、Web で見つけた他の方法が期待どおりに機能しなかったためです (特にアンチエイリアシングの場合、これは私にとって完璧なソリューションです)。
これは、Web サイトから取得した drawLine 関数です: http://willperone.net/Code/codeline.php
void ColoringScene::drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int a, unsigned char* data, unsigned char* areasData){
int dy = y2 - y1;
int dx = x2 - x1;
int stepx, stepy;
if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
setPixelWithCheckingArea(x1, y1, r, g, b, a, data, areasData);
if (dx > dy)
{
int fraction = dy - (dx >> 1); // same as 2*dy - dx
while (x1 != x2)
{
if (fraction >= 0)
{
y1 += stepy;
fraction -= dx; // same as fraction -= 2*dx
}
x1 += stepx;
fraction += dy; // same as fraction -= 2*dy
setPixelWithCheckingArea(x1, y1, r, g, b, a, data, areasData);
}
} else {
int fraction = dx - (dy >> 1);
while (y1 != y2) {
if (fraction >= 0) {
x1 += stepx;
fraction -= dy;
}
y1 += stepy;
fraction += dx;
setPixelWithCheckingArea(x1, y1, r, g, b, a, data, areasData);
}
}
}