EDIT: Non ero sicuro se questa dovrebbe essere una nuova domanda o no, quindi sto aggiornando questo per ora. Il fiocco di neve viene ora generato correttamente, a meno che non cambi le coordinate originali. Ad esempio, se il mio triangolo originale è come l'immagine 1, il risultato dopo 5 iterazioni è immagine 2:Impossibile ruotare il fiocco di neve Koch
Tuttavia, se il mio triangolo originale è qualcosa di diverso, ad esempio foto 3, i risultati sono a privilegiare l':
ho di nuovo che il problema è con i miei normali, ma sono davvero perso. Ho cercato per ore di capire le formule corrette per farlo, ma non sto facendo alcun progresso. Dato che sembra che molte volte il problema sia rappresentato dall'inversione dei nuovi triangoli, sospetto che atan mi stia dando un valore negativo quando dovrebbe darmi un valore positivo. C'è un modo matematico per aggirare questo? Grazie mille per il vostro aiuto!
Il mio codice (meno le porzioni openGL perché io non credo che siano il problema) è:
const int NumTimesToSubdivide = 5;
const int NumSegments = 3072; // 3x4^n lines generated {3, 12, 48, 192, 768, 3072..}
const int NumVertices = NumSegments * 2; // 2 vertices for each segment
vec2 arrayA[NumVertices];
vec2 arrayB[NumVertices];
//----------------------------------------------------------------------------
void koch(const vec2 &a, const vec2 &b, vec2 * verts) {
/* Calculate new segments.
* v1
* /\
* /\
* / \
* a----/ \----b
* v0 v2
*/
vec2 v0;
vec2 v1;
vec2 v2;
GLfloat distance(sqrt(pow(b.x - a.x, 2) + pow(b.y - a.y,2)));
GLfloat deltaX = abs(b.x - a.x);
GLfloat deltaY = abs(b.y - a.y);
GLfloat normalX((b.x - a.x)/deltaX);
GLfloat normalY((b.y - a.y)/deltaY);
GLfloat theta = atan2(b.y - a.y, b.x - a.x) - M_PI/3.0;
cout << " theta = " << theta << endl;
/*************************
* Find trisection points
*************************/
// horizontal line _____________
if(a.y == b.y) {
vec2 temp0(a.x + (deltaX * normalX/3) , a.y);
vec2 temp2(a.x + (deltaX * normalX * 2/3) , a.y);
vec2 temp1((a.x + b.x)/2, a.y + distance * sin(theta)/3);
v0 = temp0;
v2 = temp2;
v1 = temp1;
}
// |
// vertical line |
// |
else if(a.x == b.x){
vec2 temp0(a.x , (a.y + (deltaY * normalY/3)));
vec2 temp2(a.x , (a.y + (deltaY * normalY * 2/3)));
vec2 temp1(a.x + distance * cos(theta)/3 , (a.y + b.y)/2);
v0 = temp0;
v2 = temp2;
v1 = temp1;
}
// slope != 0 && slope != 1
else {
vec2 temp0(a.x + (deltaX * normalX/3), a.y + (deltaY * normalY/3));
vec2 temp2(a.x + (deltaX * normalX * 2/3), a.y + (deltaY * normalY * 2/3));
// Andrew is the greatest!
vec2 temp1(temp0.x + distance * cos(theta)/3,
temp0.y + distance * sin(theta)/3);
v0 = temp0;
v2 = temp2;
v1 = temp1;
}
verts[0] = a;
verts[1] = v0;
verts[2] = v0;
verts[3] = v1;
verts[4] = v1;
verts[5] = v2;
verts[6] = v2;
verts[7] = b;
}
//----------------------------------------------------------------------------
void divide_line(const vec2& a, const vec2& b, const vec2& c, int n)
{
// arrayA = {a, b, b, c, c, a} i.e., the sides of the initial triangle
arrayA[0] = a;
arrayA[1] = b;
arrayA[2] = b;
arrayA[3] = c;
arrayA[4] = c;
arrayA[5] = a;
// If at least one iteration:
if(n > 0) {
// The current iteration, starting with 0
int currentIteration = 1;
// Do for every iteration from 0 - n:
while (currentIteration <= n) {
int i;
int j = 0;
int size = 3 * 2 * (pow(4,currentIteration-1));
// Call koch() for each pair of vertices in arrayA
for(i = 0; i < size; i = i+2) {
vec2 verts[8];
koch(arrayA[i], arrayA[i+1], verts);
// Store each vertex in arrayB
int k;
for(k = 0; k <= 7; k++)
arrayB[j++] = verts[k];
}
// Copy arrayB to arrayA for next iteration.
size = 3 * 2 * pow(4, currentIteration);
for(i = 0; i < NumVertices; i++) {
arrayA[i] = arrayB[i];
}
// Increase count of currentIteration.
currentIteration++;
}
} else
printf("The number of iterations must be >= 0.\n");
}
Attualmente sto cercando di implementare la curva di Koch in C++. Ho quasi funzionato correttamente. Ci sono fondamentalmente tre diversi casi che sto affrontando: il segmento di linea che ho bisogno di suddividere in quattro segmenti è orizzontale, verticale o altro.
Il problema è che quando il programma calcola quali sono i nuovi vertici per i segmenti di linea, ci sono due possibilità: il triangolo può essere rivolto verso l'alto o il triangolo può essere rivolto verso il basso. Ho cercato di tenerne conto normalizzando i vettori, ma l'ho fatto in modo errato o c'è qualcos'altro di leggermente fuori. Le immagini qui sotto sono due esempi; entrambi hanno 3 iterazioni del frattale.
Il codice per suddividere un segmento di linea non orizzontale e non verticale è inferiore, poiché i triangoli sembrano faccia nel modo giusto per segmenti orizzontali verticali /:
if(a.x == b.x) {
...
}
else if (a.y == b.y) {
...
}
// slope != 0 && slope != 1
else {
GLfloat deltaX = abs(b.x - a.x);
GLfloat deltaY = abs(b.y - a.y);
vec2 temp0(a.x + (deltaX * normalX/3), a.y + (deltaY * normalY/3));
vec2 temp2(a.x + (deltaX * normalX * 2/3), a.y + (deltaY * normalY * 2/3));
GLfloat dist(sqrt(pow(temp2.x - temp0.x, 2) + pow(temp2.y - temp0.y,2)));
GLfloat theta = (a.x - b.x)/ (b.y - a.y);
vec2 temp1((a.x + b.x)/2 + dist * cos(atan(theta)) ,
(a.y + b.y)/2 + dist * sin(atan(theta)));
v0 = temp0;
v2 = temp2;
v1 = temp1;
}
a e b sono i vettori del segmento. NormalX e normalY sono:
GLfloat normalX((b.x - a.x)/(abs(b.x - a.x)));
GLfloat normalY((b.y - a.y)/(abs(b.y - a.y)));
Qualche idea di cosa posso fare per risolvere questo problema?
Cosa sono qui 'a' e 'b'? Sarebbe più facile se pubblicassi più codice. – sinelaw
GLfloat normalX ((b.x - a.x)/deltaX); GLfloat normalY ((b.y - a.y)/deltaY); dovrebbe essere GLfloat normalX ((b.x - a.x)/distance); GLfloat normalY ((b.y - a.y)/distance); - i tuoi valori saranno tutti +1 o -1 –