Download NetBeans IDE 5

Document related concepts
no text concepts found
Transcript
NetBeans IDE 5.5: GUÍA RÁPIDA (Continuación)
Construcción, documentación, distribución y uso de paquetes
Autor: Físico, M Sc., Diego Luis Aristizábal Ramírez, profesor asociado, Escuela de Física, UN.
Universidad Nacional de Colombia sede Medellín
Copyright 2007
Bienvenido a NetBeans IDE!
A continuación se construirá un paquete denominado física. Al mismo se le generará su
documentación y se empaquetará para su distribución. Por último se implementará una
aplicación que haga uso del paquete generado.
El paquete tendrá la siguiente estructura:

fisica
o
o
contenedores
 JFrameSimulacionesFisica.java
 JPanelSimulacionesFisica.java
 Dibujable.java
objetos_laboratorio
 mecanica
 Resorte.java
 Bloque.java
 Regla.java
 Flecha.java
 Polea.java
I. El paquete física.jar
Construcción del paquete
Paso 1: Abrir el IDE NetBeans.
Paso 2: Seleccionar en el menú, File > New Project … > y se abrirá la siguiente ventana,
1
Paso 3: Seleccionar General > Java Class Library y oprima el botón Next >. Se abrirá la
siguiente ventana,
Escribir en el campo Project Name : física y en el campo Project Location:
c:\ejemplo_paquete que corresponderá a la carpeta donde se ubicará el proyecto (se
puede escoger otra carpeta). Oprimir el botón Finish. El panel Projects deberá tener el
aspecto que ilustra el cuadro rojo en la siguiente figura.
Paso 4: Ubicar el cursor sobre la etiqueta física y hacer clic derecho en el ratón. En el
popmenú desplegado seleccionar, New > Java Package y se desplegará la siguiente
ventana,
2
Escribir en el campo Package Name: contenedores y oprimir el botón Finish.
Paso 5: Repetir el paso 4 pero ahora se escribirá en el nombre del paquete,
objetos_laboratorio. El panel Projects deberá tener ahora el siguiente aspecto,
Paso 6: Ubicar el cursor en el árbol de Projects en la etiqueta objetos_laboratorio y hacer
clic derecho en el ratón. En el popmenú desplegado seleccionar New > Java Package y se
desplegará
de
nuevo
la
ventana
para
nombrar
el
paquete:
escribir
física.objetos_laboratorio.mecanica y oprima el botón Finish. El panel de Projects
adopta ahora la siguiente forma,
3
Esto significa que la estructura del paquete física tiene ahora la siguiente forma:

fisica
o
o
contenedores
objetos_laboratorio
 mecanica
A continuación se procederá a agregar las clases,
Paso 7: En el árbol del panel Projects ubicar el cursor en la etiqueta
física.contenedores y hacer clic derecho en el ratón. En el popmenú desplegado
escoger New > Java Interface y se abrirá la siguiente ventana.
Escribir en Class Name, Dibujable y oprimas Finish. Observar que se ha generado un
código fuente. Completarlo hasta quedar como sigue,
package fisica.contenedores;
import java.awt.Graphics;
4
import fisica.contenedores.*;
public interface Dibujable {
public void dibujese(JPanelSimulacionesFisica panel,Graphics g);
}
Observar que el IDE señala errores. Obviarlos por ahora.
Paso 8: En el árbol del panel Projects ubicar el cursor en la etiqueta
física.contenedores y hacer clic derecho en el ratón. En el popmenú desplegado
escoger New > Java Class y se abrirá la siguiente ventana.
Escribir en Class Name, JPanelSimulacionesFisica y oprimas Finish. Observar que se ha
generado un código fuente. Completarlo hasta quedar como sigue,
package fisica.contenedores;
import java.awt.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.awt.geom.*;
import javax.swing.*;
import fisica.contenedores.*;
/**
*
* @author Administrador
*/
public class JPanelSimulacionesFisica extends JPanel{
//variable de instancia
private ArrayList v=new ArrayList();;
Dibujable dib;
Iterator it;
//dimensiones del contenedor de este JPanel
private double escala_x=1;
private double escala_y=1;
private boolean bandera;
///variables para implementar el doble bufer
5
private Image bg;
private Graphics2D
bgg;
/**
Construye un panel para pegar los objetos Dibujables (instrumentos).
*/
public JPanelSimulacionesFisica(){
super(new FlowLayout());
this.setBackground(Color.white);
}
/**Con este método se pegan los objetos Dibujable al panel
*/
public void adicionarObjetoDibujable(Dibujable dib){
this.dib=dib;
v.add(dib);
}
public void setEscalable(boolean bandera ){
this.bandera=bandera;
}
//sobrescritura del método paintComponent
public void paintComponent(Graphics g){
//Contexto gráfico en java 2
Graphics2D g2 = (Graphics2D) g;
//borra la escena para montar el próximo cuadro de la animación
g2.setColor(getBackground());
g2.fillRect(0,0,this.getWidth(),this.getHeight());
//el diseño se implementó haciendo el JFrame padre inicial de (400,300)
if (bandera==true){
escala_x=(this.getParent()).getWidth()/600.0;
escala_y=(this.getParent()).getHeight()/400.0;
}
g2.scale(escala_x,escala_y);
//para agregar automáticamente cada objeto dibujable en el panel
it=v.iterator();
while(it.hasNext()){
dib =(Dibujable)it.next();
if(dib!=null){
dib.dibujese(this,g2);
}
}
g2.scale(1/escala_x,1/escala_y);
}//fin paintComponent
}
Hacer lo mismo para crear la clase JFrameSimulacionesFisica.java con el siguiente
código,
package fisica.contenedores;
import java.awt.*;
import javax.swing.*;//importa el JFrame
import java.awt.event.*;//importa las clases que manejan el
import fisica.contenedores.*;
evento para cerrar la ventana
6
/**
*
* @author Administrador
*/
public class JFrameSimulacionesFisica extends JFrame{
/** Creates a new instance of JFrameSimulacionesFisica */
public JFrameSimulacionesFisica(JPanelSimulacionesFisica pantalla, String titulo) {
//título del frame
this.setTitle( titulo);
//define el tamaño del frame
this.setSize(600,400);
//no dejar cambiar de tamaño a la ventana
this.setResizable(true);
//pegar el panel para desplegar los objetos dibujables
this.getContentPane().add(pantalla);
//da la instrucción de hacer el frame visible
this.setVisible(true);
//fondo del frame
this.setBackground(Color.white);
//evento que nos permite cerrar la ventana
WindowListener l =new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
}; //fin evento cerrar ventana
/*avisa al programa quién es el responsable
de cerrar la ventana*/
this.addWindowListener(l);
}// fin del constructor
}
Punto 9: Proceder de forma similar para construir las clases del paquete
física.objetos_laboratorio.mecanica. Las clases tendrán el siguiente código:
Resorte.java:
package fisica.objetos_laboratorio.mecanica;
import java.awt.*;
import java.awt.geom.*;
import fisica.contenedores.*;
public class Resorte implements Dibujable{
private
private
private
private
private
double x,y,delta_x,delta_y,longitud,angulo,ancho,delta,elongacion;;
Font letra_actual;
Color color_actual;
Color color_resorte;
int numero_espiras;
/**
Médodo constructor: Crea una resorte horizontal cuya punto inicial se pintará en la posición
(x,y)
de la pantalla y cuya longitud es igual a longitud.
*/
public Resorte(double x, double y, double longitud,double ancho,int numero_espiras)
{
color_resorte = Color.black;
this.x=x;
this.y =y;
7
this.longitud=longitud;
this.ancho=ancho;
this.numero_espiras=numero_espiras;
delta=(longitud/(2*numero_espiras));
}
/**
Método para asignar el color al resorte
*/
public void setColorResorte(Color color_resorte)
{
this.color_resorte = color_resorte;
}
/**
Método para obtener el color del resorte
*/
public Color getColorResorte(){
return color_resorte;
}
/**
Método para asignar la elongación del resorte
*/
public void setElongacionResorte(double elongacion)
{
this.elongacion = elongacion;
delta=((longitud+elongacion)/(2*numero_espiras));
}
/**
Método para obtener la longitud del resorte
*/
public double getElongacionResorte(double elongacion)
{
return elongacion;
}
/**
Método para desplazar el resorte en delta_x en dirección horizontal y en delta_y en
dirección vertical.
Esto sin rotar el resorte.
*/
public void moverResorte(double delta_x, double delta_y){
this.delta_x=delta_x;
this.delta_y=delta_y;
}
/**
Método para rotar el resorte un ángulo igual a angulo (en grados) alrededor de un eje que
pasa por su punto inicial..
*/
public void moverResorte(double angulo){
this.angulo=Math.toRadians(angulo);
}
/**
Método para rotar el resorte en un ángulo igual a angulo (en grados) alrededor de un eje que
pasa por el punto (x,y).
8
*/
public void moverResorte(double x, double y,double angulo){
this.x=x;
this.y=y;
this.angulo=Math.toRadians(angulo);
}
/**
Método que dibuja el resorte
*/
public void dibujese(JPanelSimulacionesFisica panel,Graphics g){
int ancho_panel=(panel.getSize().width);
int alto_panel=(panel.getSize().height);
Graphics2D g2= (Graphics2D)g;
//Mejora la calidad del dibujo
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(color_resorte);
g2.translate(delta_x,delta_y);
//x=x+delta_x;
//y=y+delta_y;
g2.rotate(angulo,x,y);
//dibujar la primera y la última espiras
g2.draw(new Line2D.Double(x,y,x+delta,y-0.5*ancho));
g2.draw(new Line2D.Double(x+longitud+elongacion-delta,y0.5*ancho,x+longitud+elongacion,y));
//dibujar el resto de espiras
for (int i=1;i<2*numero_espiras-1;i++){
if(i%2==0){
g2.draw(new Line2D.Double(x+i*delta,y+0.5*ancho,x+(i+1)*delta,y0.5*ancho));
}
else{
g2.draw(new Line2D.Double(x+i*delta,y-0.5*ancho, x+(i+1)*delta,y+0.5*ancho));
}
}
//dibujemos un circulito en la parte inical del resote
g2.drawOval((int)(x-2),(int)(y-2),4,4);
g2.rotate(-angulo,x,y);
g2.translate(delta_x,delta_y);
}
}
Regla.java:
package fisica.objetos_laboratorio.mecanica;
import java.awt.*;
import java.awt.geom.*;
import fisica.contenedores.*;
public class Regla implements Dibujable{
//Variables de instancia
/*
Las variables (x,y) coordenadas de la esquina superior izquierda de la regla.
Las variables (a,b) coordenada por donde pasa el eje de rotación.
Las variables (desplazamiento_x,desplazamiento_y) señalan el desplazamiento de la regla.
9
La variable angulo corresponde a la rotación en grados de la regla
alrededor del eje que pasa por (a,b)
Las variables largo y alto corresponden a las dimensiones de la regla
*/
private double x,y,desplazamiento_x,desplazamiento_y,a,b,largo,ancho,angulo;
private int n;//Alcance de la escala
private double
intervalo,numero_rayas_divisiones,numero_rayas_subdivisiones,longitud_raya_grande,longitud_r
aya_corta,margen;
private Color color_fondo=Color.yellow;
private Color color_borde=new Color(252,230,75);
private Color color_rayas_pequenas=Color.black;
private Color color_rayas_grandes=Color.red;
/**
Método constructor: construye una regla de color amarillo cuya eaquina superior izquierda
está ubicada en (x,y) , de longitud igual a largo y altura igual a alto y que la máxima
lectura es n. Además numero_rayas_divisiones es el número de diviosnes,
numero_rayas_subdivisiones
es el número de subdiviones entre dos rayas grandes.
Cuidado: Se recomienda que,
(numero_rayas_divisiones/numero_rayas_subdivisiones) debe ser un entero
La máxima lectura n debe ser un múltiplo del numero_rayas_divisiones
*/
public Regla(double x,double y,double largo,double ancho,int numero_rayas_divisiones,int
numero_rayas_subdivisiones, int n){
this.x=x;
this.y=y;
this.largo=largo;
this.ancho=ancho;
this.numero_rayas_divisiones=numero_rayas_divisiones;
this.numero_rayas_subdivisiones=numero_rayas_subdivisiones;
this.n=n;
calculos();
} //Fin método constructor
private void calculos(){
margen=0.05*largo;
longitud_raya_grande=0.7*ancho;
longitud_raya_corta=0.35*ancho;
intervalo=(largo-2*margen)/numero_rayas_divisiones;
}
/**
Método para cambiar el largo de la regla
*/
public void setLargoRegla(double largo){
this.largo=largo;
}
/**
Método para obtener el largo de la regla. Regresa un número de doble precisión.
*/
public double getLargoRegla(){
return largo;
}
/**
Método para cambiar el alto de la regla
10
*/
public void setAltoRegla(double ancho){
this.ancho=ancho;
}
/**
Método para obtener el alto de la regla. Regresa un número de doble precisión.
*/
public double getAltoRegla(){
return ancho;
}
/**
Método para cambiar la máxima lectura de la regla
*/
public void setMaximaLecturaRegla(int n){
this.n=n;
}
/**
Método para obtener la máxima lectura de la regla. Regresa un número entero.
*/
public int getMaximaLecturaRegla(){
return n;
}
/**
Método para cambiar el color de la regla
*/
public void setColorRegla(Color color_fondo){
this.color_fondo=color_fondo;
} //Fin método setColorRegla
/**
Método para obtener el color de la regla regla.Regresa un objeto de tipo Color.
*/
public Color getColorRegla(){
return color_fondo;
} //Fin método setColorRegla
/**
Método para cambiar el color de las líneas pequeñas
*/
public void setColorLineasPequenas(Color color_rayas_pequenas){
this.color_rayas_pequenas=color_rayas_pequenas;
} //Fin método setColorLineas
/**
Método para obtener el color de las líneas pequeñas
*/
public Color getColorLineasPequenas(){
return color_rayas_pequenas;
} //Fin método setColorLineas
/**
Método para cambiar el color de las líneas garndes
*/
public void setColorLineasGrandes(Color color_rayas_grandes){
this.color_rayas_grandes=color_rayas_grandes;
} //Fin método setColorLineas
11
/**
Método para obtener el color de las líneas grandes
*/
public Color getColorLineasGrandes(){
return color_rayas_grandes;
} //Fin método setColorLineas
//los siguientes métoddo le dan polimorfismo de movimiento a la regla
/**
Desplaza la regla en (desplazamiento_x,deslazamiento_y)
*/
public void moverRegla(double desplazamiento_x,double desplazamiento_y){
this.desplazamiento_x=desplazamiento_x;
this.desplazamiento_y=desplazamiento_y;
}
/**
Rota la regla alrededor de un eje que pasa por (a,b) en una cantidad
en grados sexagecimales igual a desplazamiento_angular
*/
public void moverRegla(double a,double b,double angulo){
this.angulo=angulo*(Math.PI/180.0);
this.a=a;
this.b=b;
}
/**
Desplaza la regla en una cantidad (desplazamiento_x,deslazamiento_y) y a la vez
la rota alrededor de un eje que pasa por (a,b) en una cantidad
en grados sexagecimales igual a angulo.
*/
public void moverRegla(double desplazamiento_x,double desplazamiento_y,double a,double
b,double angulo){
this.desplazamiento_x=desplazamiento_x;
this.desplazamiento_y=desplazamiento_y;
this.angulo=angulo*(Math.PI/180.0);
this.a=a;
this.b=b;
}
//Método para dibujar la regla
public void dibujese(JPanelSimulacionesFisica panel,Graphics g){
//Contexto gráfico en java 2
Graphics2D g2 = (Graphics2D) g;
//Mejora la calidad del dibujo
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//Desplazamiento de la regla
g2.translate(desplazamiento_x,desplazamiento_y);
12
g2.rotate(angulo,a,b);
//Mejora la calidad del dibujo con el antialising de java 2
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(1f));
//dibujar bordes
g2.setColor(color_borde);
g2.draw(new Rectangle2D.Double(x-1, y-1, largo+2, ancho+2));
//dibujar fondo
g2.setColor(color_fondo);
g2.fill(new Rectangle2D.Double(x, y, largo, ancho));
//dibujar las rayas de las divisiones
//calibre de la raya
g2.setStroke(new BasicStroke(0.1f));
//dibujando las rayas mediante una transformación afin de traslación
//inicia for
for(int i=0;i<numero_rayas_divisiones+1;i=i+1){
//Hace una traslación (transformación afín)
g2.translate(i*intervalo,0);
if((i%numero_rayas_subdivisiones)==0){//i es múltiplo del numero_rayas_divisiones
//rayas grandes
g2.setColor(color_rayas_grandes);
g2.draw(new Line2D.Double(x+margen,y,x+margen,y+longitud_raya_grande));
//Numerar en las rayas grandes
//tipo y tamaño de letra para numerar
int tamano_letra=(int)(0.20*ancho);
//crear y asignar la letra al contexto gráfico
Font tipo_letra=new Font("NewTimes",Font.PLAIN,tamano_letra);
g2.setFont(tipo_letra);
//dibujar los números
int lectura=(int)((i*n)/(1.0*numero_rayas_divisiones));
//medida de la lectura como cadena
FontMetrics medidor_dimensiones_letra=g2.getFontMetrics(tipo_letra);
int alto_letra= medidor_dimensiones_letra.getHeight();
int ancho_letra= medidor_dimensiones_letra.stringWidth(""+lectura);
double a_1=(x+margen)-0.5*ancho_letra;
double b_1=(y+0.9*longitud_raya_grande+alto_letra);
g2.drawString(""+lectura,(int)a_1,(int)b_1);
}
else{
//rayas pequeñas
g2.setColor(color_rayas_pequenas);
g2.draw(new
Line2D.Double(x+margen,y,x+margen,y+longitud_raya_corta));
}
//Regresa al estado inicial: Devuelve la traslación (Repite la transformación afín al
revés
g2.translate(-i*intervalo,0);
}//fin for
g2.rotate(-angulo,a,b);
g2.translate(-desplazamiento_x,-desplazamiento_y);
} //Fin método dibujese
}
13
Bloque.java:
package fisica.objetos_laboratorio.mecanica;
import java.awt.*;
import java.awt.geom.*;
import fisica.contenedores.*;
/**
*
* @author Administrador
*/
public class Bloque implements Dibujable{
//Variables de instancia
/*
Las variables (x,y) son las coordenadas de su centro de masa
La variable angulo corresponde a la rotación en grados sexagecimales del bloque alrededor de
su centro de masa
La variable nombre es una cadena que marca el bloque
*/
private double x,y,largo,alto,delta_x,delta_y,angulo;
private Color color_bloque=Color.yellow;//Color de relleno de la regla
private Color color_lineas=Color.black;//Color de las líneas de la regla
private String nombre="";
private Color color_nombre=Color.black;
private int tamano=10;
/**
Método constructor: construye un bloque de color amarillo con su centro de masa ubicado
en la posición (x,y) , de longitud igual a largo y altura igual a alto y sin estar rotado
*/
public Bloque(double x,double
this.x=x;
this.y=y;
this.largo=largo;
this.alto=alto;
y,double largo,double alto){
} //Fin método constructor
/**
Método para cambiar el largo del bloque
*/
public void setLargoBloque(double largo){
this.largo=largo;
}
/**
Método para obtener el largo del bloque. Se obtiene un número de tipo double.
*/
public double getLargoBloque(){
return largo;
}
/**
Método para cambiar el alto del bloque
*/
public void setAltoBloque(double largo){
this.alto=alto;
}
/**
Método para obtener el alto del bloque. Se obtiene un número de tipo double.
*/
14
public double getAltoBloque(){
return alto;
}
/**
Método para rotar en un ángulo igual a angulo el bloque alrededor de un eje que pasa
ortogonalmente por su centro de masa.
El ángulo se debe expresar en grados sexagesimales.
*/
public void moverBloque(double angulo){
this.angulo=Math.toRadians(angulo);
}
/**
Método para desplazar el centro de masa del bloque en una cantidad delta_x, en dirección
horizontal
y en una cantidad delta_y en dirección vertical..
*/
public void moverBloque(double delta_x, double delta_y){
this.delta_x=delta_x;
this.delta_y=delta_y;
}
/**
Método para desplazar el centro de masa del bloque en una cantidad delta_x, en dirección
horizontal
y en una cantidad delta_y en dirección vertical, y a la vez rotarlo un ángulo igual a angulo
alrededor
de un eje que pasa por su centro de masa.
*/
public void moverBloque(double delta_x, double delta_y,double angulo){
this.delta_x=delta_x;
this.delta_y=delta_y;
this.angulo=Math.toRadians(angulo);
}
/**
Método para cambiar el color del bloque
*/
public void setColorBloque(Color color_bloque){
this.color_bloque=color_bloque;
} //Fin método setColorBloque
/**
Método para obtener el color del bloque. Se obtiene un objeto de tipo Color.
*/
public Color getColorBloque(){
return color_bloque;
} //Fin método setColorBloque
/**
Método para cambiar el color de las líneas
*/
public void setColorLineas(Color color_lineas){
this.color_lineas=color_lineas;
} //Fin método setColorLineas
/**
Método para obtener el color de las líneas. Se obtiene un objeto de tipo Color.
*/
public Color getColorLineas(){
15
return color_lineas;
} //Fin método getColorBloque
/**
Método para marcar el bloque: Escribir sobre él el nombre que lo identifica.
Se le asigna el color al nombre y el tamaño del mismo.
*/
public void setMarcaBloque(String nombre, Color color_nombre,int tamano){
this.nombre=nombre;
this.color_nombre=color_nombre;
this.tamano=tamano;
}
/**
Método para dibujar el bloque
*/
public
void dibujese(JPanelSimulacionesFisica panel,Graphics g){
//Contexto gráfico en java 2
Graphics2D g2 = (Graphics2D) g;
//Mejora la calidad del dibujo
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
double a_a=largo/2.0;
double b_b=alto/2.0;
g2.translate(delta_x,delta_y);
g2.rotate(angulo,(int)x,(int)y);
g2.setPaint(color_bloque);
g2.fill(new Rectangle2D.Double(x-a_a, y-b_b, largo, alto));
g2.setPaint(color_lineas);
g2.draw(new Rectangle2D.Double(x-a_a, y-b_b, largo, alto));
g2.setColor(color_nombre);
//marcarlo
Font letra=new Font("Sanserif",Font.PLAIN,tamano );
FontMetrics medir=g2.getFontMetrics(letra);
int alto_letra= medir.getHeight();
int ancho_letra= medir.stringWidth(nombre);
int p_x=0;
int p_y=0;
int ascent=medir.getAscent();
//int alto_letra=ascent;//+descent+leading;
p_x=(int)(x-a_a+((largo-ancho_letra)/2.0));
p_y=(int)(y-b_b+((alto-alto_letra)/2.0)+ascent);
g2.setFont(letra);
g2.drawString(nombre,p_x,p_y);
g2.rotate(-angulo,x,y);//
g2.translate(delta_x,delta_y);
} //Fin método dibujese
}
Polea.java:
package fisica.objetos_laboratorio.mecanica;
import java.awt.*;
16
import java.awt.geom.*;
import fisica.contenedores.*;
/**
*
* @author Administrador
*/
public class Polea implements Dibujable{
//Variables de instancia
private double x,y,desplazamiento_x,desplazamiento_y,r;
private int n;
private double alfa,desplazamiento_angular;
private Color color_polea=Color.black;
/**
Método constructor por defecto: construye una polea de color negro
cuyo centro está ubicado en (0,0) , de radio 20 y de cinco varillas
radiales
*/
Polea(){
r=20;
n=5;
calculo();
} //Fin método constructor
/**
Método constructor: construye una polea de color negro
cuyo centro está ubicado en (x,y) , de radio r y de n varillas
radiales
*/
public Polea(double x,double y,double r,int n){
this.x=x;
this.y=y;
this.r=r;
this.n=n;
calculo();
} //Fin método constructor
//Método para calcular las varillas radiales
private void calculo(){
if(n!=0){alfa=(Math.PI/180)*(360.0/n);}
}//Fin método calculo
/**
Método para cambiar el color de la polea
*/
public void setColorPolea(Color colorPolea){
this.color_polea=color_polea;
} //Fin método setColorPolea
/**
Método para retornra el color de la polea
*/
public Color getColorPolea(){
return color_polea;
}
//Métodos para mover la polea. Se emplea polimorfismo
17
/**
Método para desplazar la polea en dirección x en una cantidad igual al
desplazamiento_x y en dirección y en una cantidad igual al desplazamiento_y
*/
public void moverPolea(double desplazamiento_x, double desplazamiento_y){
this.desplazamiento_x=desplazamiento_x;
this.desplazamiento_y=desplazamiento_y;
}
/**
Método para rotar la polea en una cantidad igual al
desplazamiento_angular (medido en grados sexagesimales),
alrededor de un eje que pasa perpendicularmente por su centro
*/
public void moverPolea(double desplazamiento_angular){
this.desplazamiento_angular=desplazamiento_angular*(3.14/180);
}
/**
Método para desplazar la polea en dirección x en una cantidad igual al
desplazamiento_x y en dirección y en una cantidad igual al desplazamiento_y
y para rotarla en una cantidad igual al desplazamiento_angular
(medido en grados sexagesimales),alrededor de un eje que pasa perpendicularmente
por su centro
*/
public void moverPolea(double desplazamiento_x, double desplazamiento_y,double
desplazamiento_angular){
this.desplazamiento_x=desplazamiento_x;
this.desplazamiento_y=desplazamiento_y;
this.desplazamiento_angular=desplazamiento_angular*(3.14/180);
}
//método para dibujar
public void dibujese(JPanelSimulacionesFisica panel,Graphics g){
Graphics2D g2= (Graphics2D)g;
//Mejora la calidad del dibujo
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//Desplazamiento de la polea
g2.translate(desplazamiento_x,desplazamiento_y);
g2.rotate(desplazamiento_angular,x,y);
//Color de la polea
g2.setColor(color_polea);
g2.setStroke(new BasicStroke(1f));
//Dibuja el círculo
g2.draw(new Arc2D.Double(x-r,y-r,2*r,2*r,0,360,Arc2D.OPEN));
//Dibujo de los radios
g2.setStroke(new BasicStroke(0.1f));
for(int i=0;i<n;i++){
g2.rotate(i*alfa,x,y);
g2.draw(new Line2D.Double(x,y-r,x,y));
g2.rotate(-i*alfa,x,y);
} //fin for
//transformación afín inversa
g2.rotate(-desplazamiento_angular,x,y);
18
g2.translate(-desplazamiento_x,-desplazamiento_y);
} //Fin método dibujese
}
Flecha.java:
package fisica.objetos_laboratorio.mecanica;
import java.awt.*;
import java.awt.geom.*;
import fisica.contenedores.*;
/**
*
* @author Administrador
*/
public class Flecha implements Dibujable{
private double x,y,delta_x,delta_y,longitud,angulo;
private Color color_vector;
/**
Médodo constructor: Crea una flecha horizontal cuya "cola" se pintará en la posición (x,y)
de la pantalla y cuya longitud es igual a longitud.
*/
public Flecha(double x, double y, double longitud)
{
color_vector = Color.black;
this.x=x;
this.y =y;
this.longitud=longitud;
}
/**
Método para asignar el color a la flecha
*/
public void setColorFlecha(Color color_vector)
{
this.color_vector = color_vector;
}
/**
Método para obtener el color de la flecha
*/
public Color getColorFlecha(){
return color_vector;
}
/**
Método para asignar la longitud a la flecha
Nota: si su valor es negativo, invierte además el sentido
*/
public void setLongitudFlecha(double longitud)
{
this.longitud = longitud;
}
/**
Método para obtener la longitud de la flecha
*/
public double getLongitudFlecha(){
return longitud;
}
/**
19
Método para desplazar la "cola" de la flecha en delta_x en dirección horizontal y en delta_y
en dirección vertical.
Esto sin rotar la flecha.
*/
public void moverFlecha(double delta_x, double delta_y){
this.delta_x=delta_x;
this.delta_y=delta_y;
}
/**
Método para rotar la flecha un ángulo igual a angulo (en grados) alrededor de un eje que
pasa por su cola..
*/
public void moverFlecha(double angulo){
this.angulo=Math.toRadians(angulo);
}
/**
Método para rotar la flecha un ángulo igual a angulo (en grados) alrededor de un eje que
pasa por el punto (x,y), o sea
la cola.
*/
public void moverFlecha(double x, double y,double angulo){
this.x=x;
this.y=y;
this.angulo=Math.toRadians(angulo);
}
/**
Método que dibuja la flecha
*/
public void dibujese(JPanelSimulacionesFisica panel,Graphics g){
Graphics2D g2= (Graphics2D)g;
//Mejora la calidad del dibujo
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(color_vector);
g2.translate(delta_x,delta_y);
g2.rotate(angulo,x,y);
g2.draw(new Line2D.Double(x,y,x+longitud,y));
g2.draw(new Line2D.Double(x+0.9*longitud,y-0.02*longitud,x+longitud,y));
g2.draw(new Line2D.Double(x+0.9*longitud,y+0.02*longitud,x+longitud,y));
g2.rotate(-angulo,x,y);
g2.translate(-delta_x,-delta_y);
}
}
Particula.java
package fisica.objetos_laboratorio.mecanica;
import
import
import
import
java.awt.*;
javax.swing.*;
java.util.*;
fisica.contenedores.*;
public class
Particula
implements Dibujable {
20
//permite definir si se quiere trazar la trayectoria o no
private boolean trazo=false;
//asigna el color a la trayectoria
private Color color_trazo=Color.red;
//asigna el color a la partícula
private Color color_particula=Color.black;
//arreglos que permiten almacenar todas las posicion instantánea calculadas de la partícula
//Contenedor de datos
private Vector vector_x=new Vector();
private Vector vector_y=new Vector();
private double x,y;
/**
Método onstructor por defecto
*/
public Particula(){
}//Fin constructor
/**
Método para mover la partícula a la posición (x.y).
*/
public void moverParticula(double x,double y){
this.x=x;
this.y=y;
vector_x.addElement(new Double(x));
vector_y.addElement(new Double(y));
}//Fin mover partícula
/**
Método para autorizar el trazo de la trayectoria de la partícula.
*/
public void setTrazo(boolean trazo){
this.trazo=trazo;
}//fin método setTrazo
public void borrarTrazo(){
vector_x.clear();
vector_y.clear();
}
/**
Método para cambiar el color de la trayectoria
*/
public void setColorTrazo(Color color_trazo){
this.color_trazo=color_trazo;
}//fin método setColorTrazo
/**
Método para cambiar el color de la partícula
*/
public void setColorParticula(Color color_particula){
this.color_particula=color_particula;
}//fin método setColorParticula
/**
Método que dibuja la trayectoria seguida por la partícula
*/
private void dibujarTrazo(Graphics2D g){
21
g.setColor(color_trazo);
for (int i=0;i<vector_x.size()-1;i++){
//este if evita que se empiece a trazar sin que se haya llenado el arreglo hasta i
if(i>2){
Double valor_x=(Double)vector_x.elementAt(i);
double x_x=valor_x.doubleValue();
int a=(int)(x_x);
Double valor_y=(Double)vector_y.elementAt(i);
double y_y=valor_y.doubleValue();
int b=(int)(y_y);
Double valor_x_1=(Double)vector_x.elementAt(i+1);
double x_x_1=valor_x_1.doubleValue();
int c=(int)(x_x_1);
Double valor_y_1=(Double)vector_y.elementAt(i+1);
double y_y_1=valor_y_1.doubleValue();
int d=(int)(y_y_1);
g.drawLine(a,b,c,d);
}//fin if
}//fin for
}//fin dibujarTrazo
/**
Método que dibuja la partícula
*/
public void dibujese(JPanelSimulacionesFisica panel,Graphics g){
Graphics2D g2= (Graphics2D)g;
//Mejora la calidad del dibujo
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//dibuja la trayectoria
if(trazo==true){dibujarTrazo(g2);}
//dibuja la partícula
g2.setColor(color_particula);
g2.fillOval((int)x-3,(int)y-3,6,6);
};//Fin dibujese
}//Fin partícula
El panel Projects tendrá ahora la siguiente forma,
22
Distribución del paquete
Paso 1: En la barra del menú escoger, Build >Build Main Projects y listo.
Felicitaciones ya tiene un paquete para distribuir. Ingresar a la carpeta del proyecto y en
el directorio dist se encontrará un archivo denominado fisica.jar. Este es el que se
distribuirá.
Documentación del paquete
Para que el cliente pueda usar su paquete se le deberá entregar la documentación del
mismo. Para generarla, escoger en la barra menú Build > Generate Javadoc for “física”.
Listo.
Felcitaciones ya ha documentado el paquete. Ingresar a la carpeta del proyecto y en el
directorio dist se encontrará una carpeta denominada javadoc. En ella se hace clic en el
archivo index.html y un explorador de Internet abrirá la documentación. Se debe
observar que en la documentación sólo aparece la información que en la implementación
del código se haya encerrado en comentarios de la forma: /** XXXXX */.
En definitiva el cliente deberá poseer el archivo física.jar y la carpeta javadoc.
II. Construcción de una aplicación que haga uso del paquete física.jar
Empezar la aplicación
23
Paso 1: Ejecutar el IDE NetBeans 5.5. Seleccionar en la barra de menú, File > New
Project …En la ventana que se despliega, seleccionar General > Java Application y se
desplegará la siguiente ventana,
Escribir en el nombre del proyecto, MovimientoParabolico y en la localización del
proyecto elegir la carpeta donde se almacenará. Tengase en cuenta que la aplicación será
en contexto gráfico por lo que se desactivarán las opciones Set as Main Project y Create
Main Class. Preionar el botón Finish. El panel Projects tendrá la siguiente forma,
Paso 2: Ubicar el cursor en Source Packages y hacer clic derecho en el ratón. En el
popmenú desplegado escoger, New > JFrame Form …. En la ventana que aparece,
escriba en el nombre de la clase, AplicacionMovimientoParabolico y oprima Finish.
En el panel Design aparecerá el JFrame creado y sobre el cual pegaremos paneles y
controles.
24
Adicionar paneles para estructurar bien la GUI
Paso 3: En el panel Inspector ubicar el cursor en la etiqueta JFramey hacer clic derecho
en el ratón. En el popmenú desplegado elegir a Set Layout > GridBagLayout como
administrador de diseño de este JFrame. Es necesario anotar que este administrador de
diseño es el más difícil de manejar, sin embargo como contraparte permite diseñar GUI
más complejas: simplemente hay que tener más cuidado.
Paso 4: Agregar dos panel al Júrame y cambie el nombre de las variables así: jPanel1 por
jPanel_simulacion y jPanel2 por jPanel_controles.
Paso 5: En el árbol de Inspector ubicar el cursor en GridBagLayout y en el popmenú
desplegado seleccionar Customize y aparecerá la siguiente ventana: con
jpanel_simulación remarcado cambie los valores por los señalados en la figura.
25
Ahora con el jPanelControles remarcado cambie los valores por los señalados en la
siguiente figura,
26
Oprimir Close.
Paso 6: Aliñar los paneles. Ponerles bordes a los paneles: Al jPanel_simulación marcarlo
con la cadena Simulación y al jPanel_controles marcarlo con la cadena Controles. El
aspecto será:
27
Paso 7: En el panel Inspector definir como administrador de diseño de jPanel_controles a
GridLayout con 4 filas y 1 columna. Adiconar a este panel tres JPanel con los nombres:
jPanel_posicion_inicial, jPanel_velocidad_inicial, jPanel_botones y jPanel_posicion. Aliñar
los paneles con bordes marcados respectivamente: Posición Inicial, Velocidad Inicial,
Botones, Posición.
Compilar y ejecutar la aplicación. La apariencia de la GUI estará así,
28
Paso 8: Generar en el panel Inspector el siguiente árbol,
Compilar y ejecutar. La GUI tendrá ahora la siguiente forma,
29
Se podrá observar que los letreros difieren de los desplegados. Editar ahora en las
propiedades de cada uno de estos elementos y cambiar el atributo Text por las cadenas
necesarias para que al compilar y ejecutar de nuevo el programa se obtenga los letreros
deseados.
Implementación del código de la simulación
1. Importar el paquete fisica.jar: en el panel Projects ubicar el cursor en la etiqueta
Libraries y hacer clic derecho en el ratón. En el popmenú desplegado escoger Add
Jar/Fólder … Importar el paquete fisica.jar de la carpeta donde lo tenga ubicado. En
estos momentos el aspecto del árbol de projects tendrá la siguiente forma,
30
Para la implementación del código de la aplicación se empleará el patrón de diseño MVC
(Modelo, Vista, Controlador).
Controlador
En este caso lo conformará la clase principal AplicacionMovimientoParabolico.java
quien se encargará a través de los eventos de los botones controlar la animación de la
simulación y a través de los valores en los campos de texto de controlar las condiciones
iniciales de la simulación.
Modelo
La conformará la clase ModeloFisico.java. En contiene el modelo físico de la
simulación: en este caso ella se encarga una vez recibido las condiciones iniciales del
movimiento de calcular y devolver los valores de la posición y la velocidad de la partícula
en cualquier instante.
Vista
La vista se desplegará en un objeto de JPanelSimulacionesFisica del paquete
física.contenedores. Los objetos protagonistas de la simulación se crearán usando el
paquete física.objetos_laboratorio.mecanica: en este caso será sólo un objeto de
tipo Particula.
2. Agregar la clase ModeloFisico.java
Tal y como se ilustra en la siguiente figura, en el árbol del panel Files ubique el cursor en
classes y haga clic derecho en el ratón. En el popmenú desplegado escoja New > Java
Class …
Se desplegará la siguiente ventana,
31
En el nombre escriba ModeloFisico y oprima Finish. En el código generado complételo de
tal forma que tome la siguiente forma,
public class ModeloFisico {
private double xo,yo,vo,angulo,tiempo;
/** Creates a new instance of ModeloFisico */
public ModeloFisico() {
}
public void setValoresIniciales(double xo, double yo,double vo, double angulo){
this.xo=xo;
this.yo=yo;
this.vo=vo;
this.angulo=angulo;
}
public void setTiempo(double tiempo){
this.tiempo=tiempo;
}
//Retorna la posición en x en el instante tiempo;
public double getX(){
double x=0;
x=xo+vo*Math.cos(Math.toRadians(angulo))*tiempo;
return x;
}
32
//Retorna la posición en y en el instante tiempo;
public double getY(){
double y=0;
y=yo-vo*Math.sin(Math.toRadians(angulo))*tiempo+0.5*9.8*tiempo*tiempo;
return y;
}
//Retorna la velocidad en x en el instante tiempo;
public double getVx(){
double vx=0;
vx=vo*Math.cos(Math.toRadians(angulo));
return vx;
}
//Retorna la velocidad en y en el instante tiempo;
public double getVy(){
double vy=0;
vy=-vo*Math.sin(Math.toRadians(angulo))+9.8*tiempo;
return vy;
}
}
3. Crear el objeto responsable de desplegar la vista.
En el código de AplicacionMovimientoParabolico.java agregue el código siguiente
que se encuentra señalado con color rojo,
import fisica.contenedores.*;
import java.awt.*;
public class AplicacionMovimientoParabolico extends javax.swing.JFrame{
//Creación de un JPanelSimulacionesFisica
private JPanelSimulacionesFisica pantalla_simulacion= new JPanelSimulacionesFisica();
/** Creates new form AplicacionMovimientoParabolico */
public AplicacionMovimientoParabolico() {
initComponents();
this.setSize(600,400);
this.setResizable(false);
//peguemos
el panel de simulaciones en física a jPanel_simulacion
jPanel_simulacion.setLayout(new GridLayout(1,1));
jPanel_simulacion.add(pantalla_simulacion);
}
33
4. Crear y pegar el objeto Particula que corresponderá a la partícula que se moverá en la
vista.
En el código de AplicacionMovimientoParabolico.java agregue el código siguiente
que se encuentra señalado con color rojo,
import fisica.contenedores.*;
import fisica.objetos_laboratorio.mecanica.*;
import java.awt.*;
public class AplicacionMovimientoParabolico extends javax.swing.JFrame {
//Creación de un JPanelSimulacionesFisica
private JPanelSimulacionesFisica pantalla_simulacion= new JPanelSimulacionesFisica();
//Creación de partícula
private Particula particula=new Particula();
/** Creates new form AplicacionMovimientoParabolico */
public AplicacionMovimientoParabolico() {
initComponents();
this.setSize(600,400);
this.setResizable(false);
//peguemos
el apnel de simulaciones en física a jPanel_simulacion
jPanel_simulacion.setLayout(new GridLayout(1,1));
jPanel_simulacion.add(pantalla_simulacion);
//adicionemos la partícula a pantalla_simulacion
pantalla_simulacion.adicionarObjetoDibujable(particula);
}
5. Crear el objeto responsable de manejar el modelo físico.
En el código de AplicacionMovimientoParabolico.java agregue el código siguiente
que se encuentra señalado con color rojo,
public class AplicacionMovimientoParabolico extends javax.swing.JFrame {
//Creación de un JPanelSimulacionesFisica
private JPanelSimulacionesFisica pantalla_simulacion= new JPanelSimulacionesFisica();
//Creación de partícula
private Particula particula=new Particula();
//Creación del modelo físico
ModeloFisico modelo=new ModeloFisico();
6. Definir las variables que necesarias para almacenar las condiciones iniciales y los
métodos encargados de leer los datos y configurar la actualización de la vista.
34
En el código de AplicacionMovimientoParabolico.java agregue el código siguiente
que se encuentra señalado con color rojo,
public class AplicacionMovimientoParabolico extends javax.swing.JFrame {
//Creación de un JPanelSimulacionesFisica
private JPanelSimulacionesFisica pantalla_simulacion= new JPanelSimulacionesFisica();
//Creación de partícula
private Particula particula=new Particula();
//Creación del modelo físico
ModeloFisico modelo=new ModeloFisico();
//variables cinemáticas
private double xo,yo,vo,angulo;
/** Creates new form AplicacionMovimientoParabolico */
public AplicacionMovimientoParabolico() {
initComponents();
this.setSize(600,400);
this.setResizable(false);
//peguemos
el apnel de simulaciones en física a jPanel_simulacion
jPanel_simulacion.setLayout(new GridLayout(1,1));
jPanel_simulacion.add(pantalla_simulacion);
//adicionemos la partúla a pantalla_simulacion
pantalla_simulacion.adicionarObjetoDibujable(particula);
estadoInicial();
}
public void estadoInicial(){
leerCamposTexto();
//Exportar los valores iniciales al modelo físico
modelo.setValoresIniciales(xo,yo,vo,angulo);
actualizarPantalla();
}
private void leerCamposTexto(){
//tomar los valores de los campos de texto
String cadena_xo = jTextField_xo.getText();
Double numero_xo = Double.valueOf(cadena_xo);
xo= numero_xo.doubleValue();
String cadena_yo = jTextField_yo.getText();
Double numero_yo = Double.valueOf(cadena_yo);
yo= numero_yo.doubleValue();
35
String cadena_vo = jTextField_vo.getText();
Double numero_vo = Double.valueOf(cadena_vo);
vo= numero_vo.doubleValue();
String cadena_angulo = jTextField_angulo.getText();
Double numero_angulo = Double.valueOf(cadena_angulo);
angulo= numero_angulo.doubleValue();
}
private void actualizarPantalla(){
double x=modelo.getX();
double y=modelo.getY();
particula.moverParticula(x,y);
particula.setTrazo(true);
//aseguremos el repinte de la pantalla donde se despliega la patícula
pantalla_simulacion.repaint();
//indicar la psoición en la estiquetas label de X e Y con dos decimales
x=(Math.floor(100*x))/100;
y=(Math.floor(100*y))/100;
jLabel_x.setForeground(Color.red);
jLabel_x.setText("x (m)="+x);
jLabel_y.setForeground(Color.red);
jLabel_y.setText("y (m)="+y);
}
7. Hacer que la aplicación genera animación.
En el código de AplicacionMovimientoParabolico.java agregue el código siguiente
que se encuentra señalado con color rojo,
public class AplicacionMovimientoParabolico extends javax.swing.JFrame implements Runnable{
//Creación de un JPanelSimulacionesFisica
private JPanelSimulacionesFisica pantalla_simulacion= new JPanelSimulacionesFisica();
//Creación de partícula
private Particula particula=new Particula();
//Creación del modelo físico
ModeloFisico modelo=new ModeloFisico();
//variables cinemáticas
private double xo,yo,vo,angulo,tiempo;
//hilo de animacion
private Thread hilo;
//bandera
private boolean on=false;
//paso
36
private double dt=0.05;
//arrancar la animación
public void arrancar(){
hilo=new Thread(this);
hilo.start();
}
//parar la animación
public void detener(){
//mata el hilo
hilo = null;
}
public void run(){
while(hilo!=null &on==true){
try{
tiempo=tiempo+dt;
modelo.setTiempo(tiempo);
actualizarPantalla();
Thread.sleep(25);
//parar el hilo
if(tiempo>100.0){detener();}//fin if
}//fin try
catch(InterruptedException e){}//fin catch
}//fin while
}//fin run
8. Generar los eventos en los botones.
Con el IDE en el modo Design (ver figura siguiente) ubique el cursor en jButton_iniciar
del árbol Inspector hacer clic derecho en el ratón y en el popmenú desplegado escoger
Events > Action > actionPerformed. En donde quede sumergido el cursor agregar el
siguiente código (código en rojo),
private void jButton_iniciarActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if(jButton_iniciar.getText().equals("Nuevo")){
jButton_pare_siga.setText("Pare");
on=false;
leerCamposTexto();
jButton_iniciar.setText("Iniciar");
} else{
particula.borrarTrazo();//borra la trayectoria vieja
37
estadoInicial();
tiempo=0.0;
modelo.setTiempo(tiempo);
on=true;
jButton_iniciar.setText("Nuevo");
arrancar();
}
}
Repita lo mismo para jButton_pare_siga y agregue el siguiente código,
private void jButton_pare_sigaActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if(jButton_pare_siga.getText().equals("Pare")){
on=false;
jButton_pare_siga.setText("Siga");
}else {
38
on=true;
arrancar();
jButton_pare_siga.setText("Pare");
}
}
9. Para mejorar la aplicación agregar el siguiente código marcado en rojo,
private void jButton_iniciarActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if(jButton_iniciar.getText().equals("Nuevo")){
activar_campos_texto();
jButton_pare_siga.setText("Pare");
on=false;
leerCamposTexto();
jButton_iniciar.setText("Iniciar");
} else{
particula.borrarTrazo();//borra la trayectoria vieja
estadoInicial();
tiempo=0.0;
modelo.setTiempo(tiempo);
desactivar_campos_texto();
on=true;
jButton_iniciar.setText("Nuevo");
arrancar();
}
}
//desactivar los campos de texto
private void desactivar_campos_texto(){
jTextField_xo.setEnabled(false);
jTextField_yo.setEnabled(false);
jTextField_vo.setEnabled(false);
jTextField_angulo.setEnabled(false);
}
//activar los campos de texto
private void activar_campos_texto(){
jTextField_xo.setEnabled(true);
jTextField_yo.setEnabled(true);
jTextField_vo.setEnabled(true);
jTextField_angulo.setEnabled(true);
}
39
Compilar y ejecutar. Haga clic en el botón Iniciar. El aspecto de la aplicación ejecutada es
algo parecido a lo siguiente,
Felicitaciones, dio otro GRAN PASO en el desarrollo de software empleando el NetBeans
5.5.
TAREA:
1.
En el paquete física.objetos_laboratorio.mecanica agregar
una clase
denominada Palito.java que consiste en un palito (rígido). Debe poder dibujarse en
un objeto de JPanelSimulacionesFisica, además impelemente polimorfismo
estático en un método llamado moverPalito que permita realizar la cinemática del
mismo (traslación de su centro de masa y rotación alrededor de su centro de
masa).
2.
Desarrolle una aplicación muy parecida a la aplicación de movimiento parabólico
desarrollada aquí pero en lugar de moverse una partícula, se tendrá un palito que
se lanzó. En la vista se debe desplegar:
a. El palito desplazándose parabólicamente y rotando alrededor de un eje que
pasa por su centro de masa.
b. La trayectoria del centro de masa y las trayectorias de las partículas de los
extremos del palito: las tres con diferente color.
40