EDITAR: No estaba seguro de si esta debería ser una pregunta nueva o no, así que solo estoy actualizando esta por el momento. El copo de nieve ahora se está generando correctamente, a menos que cambie las coordenadas originales. Por ejemplo, si mi triángulo original es como la imagen 1, el resultado después de 5 iteraciones es cuadro 2:No se puede rotar el copo de nieve Koch
Sin embargo, si mi triángulo original es algo diferente, por ejemplo la imagen 3, los resultados son asimétricos:
vuelvo a pensar que el problema es con mis normales pero estoy realmente perdido. He intentado durante horas encontrar las fórmulas correctas para hacer esto, pero realmente no estoy progresando. Como parece que muchas veces el problema es que los triángulos nuevos se invierten, sospecho que atan me está dando un valor negativo cuando debería darme un valor positivo. ¿Hay alguna forma matemática que pueda evitar esto? ¡Muchas gracias por tu ayuda!
Mi código (menos las porciones OpenGL, porque no creo que ellos son el problema) es:
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");
}
actualmente estoy tratando de poner en práctica la curva de Koch en C++. Lo tengo casi funcionando correctamente. Básicamente, hay tres casos diferentes a los que me estoy refiriendo: el segmento de línea que necesito dividir en cuatro segmentos es horizontal, vertical u otro.
El problema es que cuando el programa calcula qué son los nuevos vértices para los segmentos de línea, hay dos posibilidades: el triángulo puede mirar hacia "arriba" o el triángulo hacia "abajo". Traté de tener esto en cuenta al normalizar los vectores, pero o hice esto incorrectamente o hay algo más levemente apagado. Las imágenes a continuación son dos ejemplos; ambos tienen 3 iteraciones del fractal.
El código para dividir un segmento de línea no horizontal y no vertical está por debajo, ya que los triángulos parecen como la cara de la manera correcta para segmentos horizontales verticales /:
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 y b son los vectores del segmento. El normalX y en principio son:
GLfloat normalX((b.x - a.x)/(abs(b.x - a.x)));
GLfloat normalY((b.y - a.y)/(abs(b.y - a.y)));
¿Alguna idea de lo que puedo hacer para solucionar este problema?
¿Qué son 'a' y 'b' aquí? Sería más fácil si publicaras más código. – sinelaw
GLfloat normalX ((b.x - a.x)/deltaX); GLfloat normalY ((b.y - a.y)/deltaY); debería ser GLfloat normalX ((b.x - a.x)/distancia); GLfloat normalY ((b.y - a.y)/distancia); - tus valores serán todos +1 o -1 –