Foros del Web » Programando para Internet » Javascript »

[SOLUCIONADO] Rotacion 2D

Estas en el tema de Rotacion 2D en el foro de Javascript en Foros del Web. Hola muy buenas noches! Este es mi primer trabajo con geometría aplicada y lo que intento es ROTAR una figura. En este caso el motor ...
  #1 (permalink)  
Antiguo 20/11/2013, 02:06
 
Fecha de Ingreso: diciembre-2004
Mensajes: 721
Antigüedad: 19 años, 3 meses
Puntos: 2
Rotacion 2D

Hola muy buenas noches! Este es mi primer trabajo con geometría aplicada y lo que intento es ROTAR una figura. En este caso el motor es SVG pero la logica es algo general y es en donde radica mi error.

Mi funcion draw(grados) dibuja la figura en el angulo "grados" de rotacion que recibe como parametro. Si corre solo una vez, funciona, si corre mas de una vez, falla y dibuja una figura deforme.

La logica de mi funcion draw(grados) es {
1- Establece el punto de origen en el CENTRO de mi figura
2- Para cada punto:
a. Obtiene el angulo que se forma entre el Punto de origen y el Punto
b. Calcula las coordenadas del punto rotado al nuevo angulo
3- Dibuja la figura

}

Ya no se mas qué probar, no entiendo bien en qué estoy fallando. La primera vez que se corre funciona bien con cualquier angulo entre 1 y 360.

Código HTML:
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8"/>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<title>123 probando SVG</title>
<style type="text/css">
HTML,BODY {
	width:100%;
	height:100%;
	border: rgba(0,0,0,1);
}

#canvas {
	position:absolute;
	top:0;
	left:0;
	border:1px #333333 solid;
}
</style>

<script>

// Esto es para acceder al DOM de la SVG
var svgDoc;
function startup(evt){
  svgDoc=evt.target.ownerDocument;
}

// Load event de mi HTML
$(document).ready(function() {

	// Dibujar el rectangulo a 45 grados
	draw(45);

});

// #1 - Defino mi RECTANGULO con 4 puntos
var matriz = Array({x:250,y:150},{x:250,y:250},{x:450,y:250},{x:450,y:150});


// #2 - Funcion para dibujar la figura en un angulo dado por medio
//		de la rotacion de cada uno de sus puntos
function draw(grados) {

	// Este es el punto de origen: corresponde al CENTRO de la figura y lo estoy
	// estableciendo de forma MANUAL en esta pruebita.
	// 250 y 150 son valores literales de "ajuste" en el eje cartesiano
	// ya que estoy dibujando en el centro de mi canvas
	var Ox = 250 + ((450 - 250) / 2);
	var Oy = 150 + ((250 - 150) / 2);

	var angulo = 0;
	var r=150;		// Valor relativo al tamaño que tendrá mi figura

	/** Recorrido de puntos del poligono **/
	for (var i=0; i<4; i++) {	

		// Lo primero es calcular el ANGULO del punto, su valor inicial al que le
		// voy a sumar la cantidad de "GRADOS"
		angulo = Math.atan2(matriz[i].y - Oy, matriz[i].x - Ox) * 180 / Math.PI;

		// Luego calculo el X y el Y del nuevo punto, R es la Hipotenusa
		// Nuevamente: 250 y 150 son valores literales de "ajuste"
		matriz[i].x = 250 + r * Math.sin((grados - 90 + angulo) * Math.PI / 180);
		matriz[i].y = 150 - r * Math.cos((grados - 90 + angulo) * Math.PI / 180);
	}

	// Esta funcion es la que dibuja la figura en funcion de los valores en la variable 'matriz'
	trazarFigura();
}

// #3 - Funcion para dibujar las lineas de mi figura rectangular
function trazarFigura() {
	var linea = document.getElementById("line1");
	linea.setAttribute("x1", matriz[0].x);
	linea.setAttribute("y1", matriz[0].y);
	linea.setAttribute("x2", matriz[1].x);
	linea.setAttribute("y2", matriz[1].y);

	linea = document.getElementById("line2");
	linea.setAttribute("x1", matriz[1].x);
	linea.setAttribute("y1", matriz[1].y);
	linea.setAttribute("x2", matriz[2].x);
	linea.setAttribute("y2", matriz[2].y);

	linea = document.getElementById("line3");
	linea.setAttribute("x1", matriz[2].x);
	linea.setAttribute("y1", matriz[2].y);
	linea.setAttribute("x2", matriz[3].x);
	linea.setAttribute("y2", matriz[3].y);

	linea = document.getElementById("line4");
	linea.setAttribute("x1", matriz[3].x);
	linea.setAttribute("y1", matriz[3].y);
	linea.setAttribute("x2", matriz[0].x);
	linea.setAttribute("y2", matriz[0].y);
}

</script>

</head>
<body>

<svg id="canvas" onload="startup(evt)" width="500" height="500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve">
	<line id="line1" stroke-linecap="round" x1="0" y1="0" x2="0" y2="0" stroke-width="4" stroke="black" />
	<line id="line2" stroke-linecap="round" x1="0" y1="0" x2="0" y2="0" stroke-width="4" stroke="black" />
	<line id="line3" stroke-linecap="round" x1="0" y1="0" x2="0" y2="0" stroke-width="4" stroke="black" />
	<line id="line4" stroke-linecap="round" x1="0" y1="0" x2="0" y2="0" stroke-width="4" stroke="black" />
</svg>

</body>
</html> 
¡Si me ayudan se los agradeceré muchisimo!

Saludos
  #2 (permalink)  
Antiguo 20/11/2013, 03:40
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 3 meses
Puntos: 206
Respuesta: Rotacion 2D

El centro que tiene la matriz original no es el mismo centro que tiene la matriz cuando la "tratas" con tu función draw, porque le cambia el tamaño y la posición. Asi que deberás calcular el centro cada cez que ejecutes draw.

Por otra parte, para rotar figuras en 2D se utiliza la matriz de rotación y la matriz de traslación.
Tienes una matriz con las coordenadas X e Y de todos los vértices, y otra matriz con sólo la coordenada X e Y del punto por donde quieres rotar.

Se resta a cada coordenada X de los vértices, la coordenada X de rotación. Con la coordenada Y, igual. Con eso se consigue situar el centro en la coordenada (0,0), para que la rotación sea correcta.
Luego se multiplica la matriz por otra matriz llamada de rotación, que básicamente contiene los valores de seno y coseno del ángulo con el que quieres rotar.
La matriz resultado estará rotada sobre el eje (0,0). Por último se le suma a cada vertice de la matriz, su correspondiente coordenada del centro (antes se restó, ahora se suma). Así moverías la matriz con los vértices rotados, a su posición original.
Y con ésto, ya está la matriz rotada.
http://jsfiddle.net/Zjt4R/1/

Última edición por marlanga; 20/11/2013 a las 03:52
  #3 (permalink)  
Antiguo 20/11/2013, 09:48
 
Fecha de Ingreso: diciembre-2004
Mensajes: 721
Antigüedad: 19 años, 3 meses
Puntos: 2
Respuesta: Rotacion 2D

Hola Marlanga, como estas? Gracais por tu respuesta.

Respecto al punto de origen o centro en realidad la funcion no cambia tamaño ni posicion de la figura ya que este punto de origen es el centro mismo de la figura, en teoria, es un punto constante ya que la figura rota sobre su propio eje... pero ahora quede algo confundido.

Abrazo!
  #4 (permalink)  
Antiguo 20/11/2013, 09:55
 
Fecha de Ingreso: diciembre-2004
Mensajes: 721
Antigüedad: 19 años, 3 meses
Puntos: 2
Respuesta: Rotacion 2D

Cita:
Iniciado por marlanga Ver Mensaje
El centro que tiene la matriz original no es el mismo centro que tiene la matriz cuando la "tratas" con tu función draw, porque le cambia el tamaño y la posición. Asi que deberás calcular el centro cada cez que ejecutes draw.

Por otra parte, para rotar figuras en 2D se utiliza la matriz de rotación y la matriz de traslación.
Tienes una matriz con las coordenadas X e Y de todos los vértices, y otra matriz con sólo la coordenada X e Y del punto por donde quieres rotar.

Se resta a cada coordenada X de los vértices, la coordenada X de rotación. Con la coordenada Y, igual. Con eso se consigue situar el centro en la coordenada (0,0), para que la rotación sea correcta.
Luego se multiplica la matriz por otra matriz llamada de rotación, que básicamente contiene los valores de seno y coseno del ángulo con el que quieres rotar.
La matriz resultado estará rotada sobre el eje (0,0). Por último se le suma a cada vertice de la matriz, su correspondiente coordenada del centro (antes se restó, ahora se suma). Así moverías la matriz con los vértices rotados, a su posición original.
Y con ésto, ya está la matriz rotada.
http://jsfiddle.net/Zjt4R/1/
¡No habia visto el JSFIDLE! Que genio que sos lo hiciste andar !!!

Veo que recalculas el punto de origen pero no comprendo cual es la logica digamos, yo suponia que era siempre un punto fijo.

En otras webs que estuve visitando vi que hacian la rotacion del punto de la misma forma que lo estas haciendo vos:

Código HTML:
        matriz[i].x=(x*cos-y*sen)+Ox;
        matriz[i].y=(x*sen+y*cos)+Oy;
¿Esta forma seria equivalente a utilizar la matriz de rotacion?


Gracias por tu aporte, me alegraste muchisimo el día... es todo un mundo nuevo para esto de la geometría en programación, estoy "aprendiendo a caminar" de nuevo casi.

Gran abrazo!

edu
  #5 (permalink)  
Antiguo 20/11/2013, 15:09
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 3 meses
Puntos: 206
Respuesta: Rotacion 2D

En mi código, no haría falta calcular la posición central cada vez que se rota, porque no se mueve.

Y ese trozo de código que has puesto, mezla rotación con traslación.

Traslación (muevo el rectangulo al origen de coordenadas 0,0. Como sé que el centro es (Ox, Oy), resto cada componente a las coordenadas de cada vértice del cuadrado.
Código Javascript:
Ver original
  1. var x=matriz[i].x-Ox;
  2. var y=matriz[i].y-Ox;

Rotación:
Código Javascript:
Ver original
  1. var cos=Math.cos(radianes);
  2. var sen=Math.sin(radianes);
  3. matriz[i].x=(x*cos-y*sen);
  4. matriz[i].y=(x*sen+y*cos);

Traslación, muevo el rectángulo a donde estaba.
Código Javascript:
Ver original
  1. matriz[i].x= matriz[i].x+Ox;
  2.  matriz[i].y= matriz[i].y+Oy;


Una matriz se puede ver como una colección de coordenadas. Es decir, un array bidimensional (o cualquier estructura de datos, como la que tú usas). Sobre las matrices se pueden hacer 3 operaciones matemáticas, que son la traslación, la rotación, y la escalación. La translación sirve para mover una matriz de coordenadas hacia el punto (x,y) que quieras. Se hace sumando a cada componente X de cada vertice de la matriz, la coordenada X del punto. Con la coordenada Y igual.

La rotación sirve para rotar cada vértice de un array de vértices con el ángulo que quieras. Solo hay que saber que siempre se rotará sobre el origen de coordenadas, es decir, sobre (0,0).

La escalación sirve para aumentar o disminuir la distancia de cada vértice con el origen de coordenadas, y se hace multiplicando cada componente de cada vértice, por un número dado (que se llama número escalar).

Para rotar sobre el centro de un objeto, primero hay que hacer que el centro del objeto coincida con la coordenada (0,0) Luego rotas, y por ultimo lo vuelves a trasladar a donde estaba.

para escalar, tambien es interesante mover el centro del objeto al orígen de coordenadas. Así, cuando escales, harás que el objeto aumente o disminuya de tamaño. Por ejemplo, escalar por 2 hará que el objeto sea el doble de grande. Escalar por 0.5, hará que sea la mitad de pequeño. Si escalas el objeto sin moverlo al origen de coordenadas, se deformará.
  #6 (permalink)  
Antiguo 25/11/2013, 15:37
 
Fecha de Ingreso: diciembre-2004
Mensajes: 721
Antigüedad: 19 años, 3 meses
Puntos: 2
Respuesta: Rotacion 2D

Marlanga, gracias por la respuesta!!! Estuve haciendo muchas pruebas estos días, me sirvio mucho tu respuesta!

Ante nada te pregunto ¿qué lectura podrias recomendarme? yo quisiera aprender más sobre la implementacion de geometría/fisica en programación pero la verdad todo lo que encuentro me ha servido poco a la hora de implementarlo como algoritmo.

Estuve haciendo varias pruebas, algunas cosas utiles que hice fue capturar la posicion inicial del vector para rotarlo con más comodidad a un angulo especifico. Luego jugue con las escalas y translaciones, estoy muy cebado no puedo dejar la PC jajaja... ahora quiero investigar un poco como trabajar con "perspectiva" o "punto de fuga", para hacer algo estilo isométrico.

Seguro mas adelante hago un post con los avances!

Tambien estuve leyendo tu blog, muy muy muy bueno, la verdad te agradezco por tanta info que compartis

Saludos!

Etiquetas: ajax, funcion, html, jquery, js, rotacion, variable
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 10:56.