0

Quiero usar los espacios de memoria de una matriz 3D para representar una red de cubos.

Al escribir 3 for anidados para construir el cubo obtengo todos los puntos tridimensionales (i,j,k) representando los vértices de todos los cubos pero necesito etiquetar cada cubo para trabajar con sus respectivas coordenadas (x,y,z) y no con sus vertices, con etiquetar me refiero a saber que # de cubo es en el que estoy y cuales son sus coordenadas (x,y,z).

Lo siguiente crea una estructura de 10 cubos.

 #include <cstdio>    
 #include <iostream>    
 #include <cmath>                
 #include <cstdlib>        
 #include <conio.h>         

 using namespace std;

 int main(){
 int Xmax, Ymax, Zmax, Xmin, Ymin, Zmin;
 int Mcub[1][1][1] = {0};

for (int i=0; i<11; i++){
  for (int j=0; j<11; j++){
    for (int k=0; k<11; k++){

     Xmax = i+1, Xmin = i;
     Ymax = j+1, Ymin = j;    // Límites de cada dubo
     Zmax = k+1, Zmin = k; 

     Mcub[i][j][k];
     cout << "(" << i << "," << j << "," << k << ")" << endl;
     }
   }
 }

    getch();
 return 0;
}
juan
  • 7
  • 4
  • Si tienes una coordenada cualquiera `(x,y,z)`, me parece mejor aplicar alguna función de redondeo a `x` `y` y `z`, para determinar el cubo en el que se encuentra, el código está algo confuso, si yo tuviera el punto `(0.1,0.5,0.7)` ¿en que cubo debería encontrarse?, asumo que debería encontrarse en el cubo `(1,1,1)`, pero tu código no lo hace funcionar así. – 4lrdyD Feb 12 '20 at 23:58
  • Llevas ya varios días con esta pregunta ... y yo aun no la entiendo. El código que muestras **no hace nada**, mas que imprimir los valores de `i`, `j` y `k`. ¿ Para que se usan `Xmax`, `Xmin` y demás ? ¿ Y que se supone que hace `Mcub[i][j][k]` ? Solo está ahí, sin asignar ningún valor. – Trauma Feb 17 '20 at 19:30
  • quiero crear una red de cubos, cómo lo hago? la usare para analizar datos que caerán dentro de algún cubo, estaré simulando tejido biológico con cada vóxel – juan Feb 17 '20 at 19:58
  • ese código escribe todas esas combinaciones de **(i,j,k)** las cuales me representan todos los vértices de cada cubo de tamaño 1, pero no paso de ahí pues no quiero usar esos datos sino las coordenadas **(x,y,z)** de algún cubo y el número de este, los datos de salida que espero son : cubo #42 con coordenadas **(x,y,z)** – juan Feb 17 '20 at 20:03

1 Answers1

2

Voy a simplificar el problema en 2D, porque no se hacer arte ASCII en 3D, después lo extrapolamos a tres dimensiones.

Suponiendo una cuadrícula de 3×3:

  0   1   2   3
0 +---+---+---+
  |   |   |   |
1 +---+---+---+
  |   |   |   |
2 +---+---+---+
  |   |   |   |
3 +---+---+---+

La celda en la coordenada (0, 0) tiene cuatro vértices: (0, 0), (0, 1), (1, 0), (1, 1). Con esto podemos extrapolar que dada una coordenada de celda, sus vértices serán todas las combinaciones de +1 vértice en todas las dimensiones:

| Celda  |         desplazamiento         |            vértices            |
| (0, 0) | (0, 0), (0, 1), (1, 0), (1, 1) | (0, 0), (0, 1), (1, 0), (1, 1) |
| (0, 2) | (0, 0), (0, 1), (1, 0), (1, 1) | (0, 2), (0, 3), (1, 2), (1, 3) |
| (2, 2) | (0, 0), (0, 1), (1, 0), (1, 1) | (2, 2), (2, 3), (3, 2), (3, 3) |

En 3D sucede igual. De hecho sucede igual en cualquier dimensión, la celda 3D en (0, 0, 0) tiene ocho vértices: (0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)

     0,0,0         1,0,0
         +---------+
        /|        /|
       / |       / |
0,0,1 +---------+  | 1,0,1
0,1,0 |  +------|--+ 1,1,0
      | /       | /
      |/        |/
0,1,1 +---------+ 1,1,1

Sabiendo eso…

si lanzo aleatoriamente un punto deseo saber en qué cubo está usando sus coordenadas.

Un punto cualquiera (x, y, z) es un cubo compuesto por: (x, y, z), (x, y, z + 1), (z, y + 1, z), (x, y + 1, z + 1), (x + 1, y, z), (x + 1, y, z + 1), (x + 1, y + 1, z), (x + 1, y + 1, z + 1)

Edición 14-febrero-2020.

Para poder identificar cada celda por un índice, se pueden seguir las siguientes fórmulas:

Posición = (Ancho * Y) + X

X = Posición % Ancho

Y = Posición / Alto

+---+---+---+
| 0 | 1 | 2 |
+---+---+---+
| 3 | 4 | 5 |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+

Sabemos que la celda del centro de la cuadrícula 3×3 es 4 porque:

Posición = (3 × 1) + 1 ⇒ 4

Sabemos que la celda 7 es X = 1, Y = 2 porque:

X = (7 % 3) ⇒ 1, Y = (7 / 3) ⇒ 2

En tres dimensiones las fórmulas son:

Posición = (Ancho × Z) + (Ancho × Alto × Y) + X

X = Posición % Ancho

Y = Posición / (Ancho × Alto)

Z = (Posición / Ancho) % Alto

+---+---+---+\
| 0 | 1 | 2 | \
+---+---+---+  +---+---+---+\
| 9 | 10| 11|  | 3 | 4 | 5 | \
+---+---+---+  +---+---+---+  +---+---+---+
| 18| 19| 20|  | 12| 13| 14|  | 6 | 7 | 8 |
+---+---+---+  +---+---+---+  +---+---+---+
             \ | 21| 22| 23|  | 15| 16| 17|
              \+---+---+---+  +---+---+---+
                            \ | 24| 25| 26|
                             \+---+---+---+

Sabemos que la celda del centro de la cuadrícula 3×3×3 es 13 porque:

Posición = (3 × 1) + (3 × 3 × 1) + 1 ⇒ 3 + 9 + 1 ⇒ 13

Sabemos que la celda 16 es X = 1, Y = 1, Z = 2 porque:

X = 16 % 3 ⇒ 1, Y = 16 / (3 × 3) ⇒ 1, Z = (16 / 3) % 3 ⇒ 5 % 3 ⇒ 2

Detalles a tener en cuenta.

Tu código tiene errores y espacio de mejora:

  • Las cabeceras <stdio.h>, <math.h>, <stdlib.h> y <conio.h> pertenecen al lenguaje C, no al lenguaje C++. Si necesitases usarlas (que la mayoría de veces no es necesario y ciertamente no es tu caso) deberías usar la versión adaptada a C++; lee este hilo para más detalles.
  • La definición int Mcub[1][1][1] crea una formación tridimensional de un elemento en cada dimensión. Es decir: en total tienes tres enteros (int) y acceder a cualquier valor que no esté en el índice cero provocará comportamiento indefinido.
  • No inicializas ninguna variable, y no usas las variables X, Y ni Z.
  • La instrucción Mcub[i][j][k]; no hace nada, además de estar accediendo a valores fuera de la formación, provocando comportamiento indefinido.

Edición 26-febrero-2020.

Voy a intentar responder a tus comentarios en mi respuesta, por favor añádelos a tu pregunta.

Lo que genera mi código es una estructura de 10 cubos a partir de las combinaciones de (i, j, k), estas combinaciones representan los vértices de los 10 cubos de tamaño 1, cada cubo tiene 8 vértices, cada vértice es un punto (i,j,k) que se relaciona con cubos diferentes; si lanzo un punto aleatoriamente y cae por ejemplo dentro del cubo número 6, este punto tendrá las mismas coordenadas (x,y,z) que dicho cubo. Esto último de saber qué numero de cubo y qué coordenadas tiene es lo que no sé hacer.

Para empezar, no hay ninguna combinación de ancho, alto y largo que tenga como resultado 10 a no ser que uno de los componentes sea 1… que es lo mismo que no tener uno de dichos componentes. Si no tenemos claro cuál es el rango sobre el que te mueves, difícilmente podremos hacer cálculos.

Estás confundiendo índices y coordenadas, diferentes índices tienen diferentes coordenadas dependiendo de los rangos de tu colección de cubos… así pues si aseguras tener 10 cubos y están distribuidos en 2×5×1:

+-+-+
|0|1|
+-+-+
|2|3|
+-+-+
|4|5|
+-+-+
|6|7|
+-+-+
|8|9|
+-+-+

El cubo 6 tendrá la coordenada (0, 3, 0), pero si están distribuidos en 5×2×1:

+-+-+-+-+-+
|0|1|2|3|4|
+-+-+-+-+-+
|5|6|7|8|9|
+-+-+-+-+-+

El cubo 6 tendrá la coordenada (1, 1, 0). Es normal que no sepas lo que hacer si no tienes claros los conceptos ni tienes una idea clara de lo que quieres; estas carencias en tu comprensión son evidentes en tus comentarios:

Las fórmulas que me diste están un poco extrañas y no logro hacer que quede por ejemplo para una estructura de 5 cubos en cada eje, da un total de 25 cubos, entonces.

Cinco cubos en cada eje no da 25 cubos si no 125 (5 ancho, 5 alto y 5 largo o 5×5×5 o 53). Lo extraño no es la fórmula si no tu manera de entender el problema. Te comparto una implementación de las fórmulas de índice a coordenada y viceversa:

struct punto { unsigned x{},y{},z{}; };

std::ostream &operator<<(std::ostream &o, const punto &p)
{
    return o << '{' << p.x << ", " << p.y << ", " << p.z << '}';
}

template <unsigned ALTO, unsigned ANCHO, unsigned LARGO>
punto indice_a_coordenada(unsigned indice)
{
    unsigned x = indice % ANCHO;
    unsigned y = indice / (ANCHO * ALTO);
    unsigned z = (indice / ANCHO) % ALTO;
    return {x, y, z};
}

template <unsigned ALTO, unsigned ANCHO, unsigned LARGO>
unsigned coordenada_a_indice(const punto &coordenada)
{
    return {(ANCHO * coordenada.z) + (ANCHO * ALTO * coordenada.y) + coordenada.x};
}

En tu distribución de cinco cubos en cada eje, el sexto cubo 6 está en (1, 0, 1):

std::cout << indice_a_coordenada<5, 5, 5>(6); // Muestra {1, 0, 1}

Unas coordenadas aleatorias deberán estar entre 0 y 4 en cada eje, el cubo del centro de tu colección 5×5×5 tiene el índice 26:

std::cout << coordenada_a_indice<5, 5, 5>({2, 2, 2}); // Muestra 26

Puedes ver el código funcionando en Try it online!.

PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82
  • exactamente.... pero quisiera mejor etiquetar cada cubo, así dejo de trabajar con sus 8 vértices y sólo trabajaría con la etiqueta de cada cubo y es lo que no sé hacer. con etiquetar me refiero a que en vez de usar mis 8 vertices, decir por ejemplo que ese es el cubo número 1 o el 2 o el 10 o cualquier otro; aunque al final, cuando lance mi punto deseo obtener una sola coordenada **(x,y,z)** – juan Feb 13 '20 at 20:25
  • Si "etiquetar cada cubo" es lo que quieres, deberías indicarlo en la pregunta, no en los comentarios de una respuesta. – PaperBirdMaster Feb 14 '20 at 07:59
  • ok, como hago eso? dejar de usar todas las combinaciones de **i,j,k** y tener por ejemplo : cubo **6** de coordenadas **(x,y,z)** – juan Feb 17 '20 at 20:04
  • No entiendo la pregunta @juan ¿Cómo hacer qué? ¿Qué combinaciones de **i,j,k**? ¿A qué te refieres con "*cubo **6** de coordenadas **(x,y,z)***"? – PaperBirdMaster Feb 18 '20 at 12:42
  • Lo que genera mi código es una **estructura de 10 cubos** a partir de las combinaciones de **(i, j, k)**, estas combinaciones representan los vértices de los 10 cubos de tamaño 1, cada cubo tiene 8 vértices, cada vértice es un punto **(i,j,k)** que se relaciona con cubos diferentes; si lanzo un punto aleatoriamente y cae por ejemplo dentro del **cubo número 6**, este punto tendrá las mismas coordenadas **(x,y,z)** que dicho cubo. Esto último de saber **qué numero de cubo y qué coordenadas tiene** es lo que no sé hacer. – juan Feb 18 '20 at 16:58
  • las fórmulas que me diste estan un poco extrañas y no logro hacer que quede por ejemplo para una estructura de 5 cubos en cada eje, da un total de 25 cubos,entonces – juan Feb 18 '20 at 17:01
  • **posicion = (5x1)+(5x5x1)+1 = 5+25+1 = 31** – juan Feb 18 '20 at 17:04
  • **X = posicion%ancho = 31 % 5 = 1 ------- Y = posicion / (ancho x alto) = 31 / 25 = 1 ------ Z = (posicion / ancho) % alto = (31 / 5) % 5 = 6 % 5 = 1---- (1,1,1) seria el punto** – juan Feb 18 '20 at 17:10
  • @juan en mi última edición de la respuesta te puse las formulas para pasar de coordenadas a índice y de índice a coordenadas. No entiendo qué es lo que te falta: toda la información está ahí a tu disposición. – PaperBirdMaster Feb 26 '20 at 13:37
  • Cómo corro el código en Dev C++? Le agrego algo? Ayuda por favor – juan Feb 27 '20 at 02:18
  • El código lo copias y pegas, después lo ejecutas *¡et voilà!*, te he proporcionado explicaciones, código y enlaces a ejemplos ejecutables. Deberías empezar a **ENTENDER** lo que estás haciendo… si en lugar de ello esperas que otras personas descifren tus crípticas necesidades y te den todo hecho no aprenderás nada. – PaperBirdMaster Feb 27 '20 at 08:10
  • muchas gracias @PaperdBirdMaster, soy nuevo en esto, ya me di cuenta que entendía mal mi problema, gracias por ayudarme, el código lo corrí en un compilador pero me marca los siguientes warnings: `1.non-static data member initializers only available with -std=c++11 or -std=gnu++11, 2.extended initializer lists only available with -std=c++11 or -std=gnu++11, 3. para "coordenada" e "indice" me pide agregar el tipo de dato, tambien me pide declarar "coordenada"` – juan Feb 27 '20 at 15:51
  • ya aprendí varias formas no llegar a un cubo enlistado con sus coordenadas, además de todo lo que me han aportado en los comentarios, la verdad sólo llevo un cursito en youtube para C++ pero con todo lo que me han dicho, ya hasta tecleo más rápido xD gracias! – juan Feb 27 '20 at 18:19
  • y gracias tengo que compilar el código en gcc – juan Feb 27 '20 at 18:24
  • me salen los mismos warnings compilando en linux, ayuda – juan Feb 27 '20 at 20:01
  • trabajando con el primer código que puse muy mal escrito al principio obtengo los mismos datos que con el tuyo, **en cada paso de los iteradores se asigna el número de mi cubo**, las coordenadas **(x,y,z)** son la combinación de los iteradores, hasta ahí estamos bien, ahora si por ejemplo quiero que el programa me pida un punto de coordenadas **(x,y,z)** deseo que me diga que número de cubo es, o viceversa; dicho de otra forma, **qué # de paso tiene esa combinación de iteradores** – juan Feb 27 '20 at 20:34
  • en mi caso es **(i,j,k)** en el tuyo **(x,y,z)** – juan Feb 27 '20 at 20:35
  • No se de qué iteradores hablas. Si tienes dudas nuevas, te aconsejo crear una nueva pregunta en la que muestres el código con el que estás trabajando. – PaperBirdMaster Feb 28 '20 at 08:48
  • pero también dime como corrijo los errores por favor, ahorita subo mi código – juan Feb 28 '20 at 16:33
  • Si tienes dudas nuevas, te aconsejo crear una nueva pregunta en la que muestres el código con el que estás trabajando. – PaperBirdMaster Feb 28 '20 at 18:24