diff --git a/TODO.txt b/TODO.txt index a366ba5..baea3e3 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,15 +1,3 @@ -Implementar inversão de cor; -Complementar exemplo das cores mostrando as transformações do lado esquerdo; -Tornar as classes matemáticas e de formas serializáveis; - -Antialiasing em textos: - g2d.setRenderingHint( - RenderingHints.KEY_TEXT_ANTIALIASING, - RenderingHints.VALUE_TEXT_ANTIALIAS_ON ); - -Suavização da linhas: - https://www.codeproject.com/Articles/1093960/2D-Polyline-Vertex-Smoothing - Separar o exemplos? Separar a engine do componente? Traduzir documentação para inglês? diff --git a/src/br/com/davidbuzatto/jsge/core/engine/BufferStrategyEngineFrame.java b/src/br/com/davidbuzatto/jsge/core/engine/BufferStrategyEngineFrame.java index 945f750..19306d1 100644 --- a/src/br/com/davidbuzatto/jsge/core/engine/BufferStrategyEngineFrame.java +++ b/src/br/com/davidbuzatto/jsge/core/engine/BufferStrategyEngineFrame.java @@ -2771,6 +2771,24 @@ public Graphics2D getGraphics2D() { return g2d; } + /** + * Retorna se a suavização do contexto gráfico está ativa. + * + * @return Verdadeiro caso a suavização esteja ativada, falso caso contrário. + */ + public boolean isAntialiasing() { + return antialiasing; + } + + /** + * Altera a flag de controle da suavização do contexto gráfico. + * + * @param antialiasing O estado da flag. + */ + public void setAntialiasing( boolean antialiasing ) { + this.antialiasing = antialiasing; + } + /** * Rotaciona o contexto gráfico atual a partir da coordenada (0, 0). * Observação: Utilize apenas no método draw! diff --git a/src/br/com/davidbuzatto/jsge/core/engine/EngineFrame.java b/src/br/com/davidbuzatto/jsge/core/engine/EngineFrame.java index a6cc329..f7579ff 100644 --- a/src/br/com/davidbuzatto/jsge/core/engine/EngineFrame.java +++ b/src/br/com/davidbuzatto/jsge/core/engine/EngineFrame.java @@ -2742,6 +2742,24 @@ public Graphics2D getGraphics2D() { return g2d; } + /** + * Retorna se a suavização do contexto gráfico está ativa. + * + * @return Verdadeiro caso a suavização esteja ativada, falso caso contrário. + */ + public boolean isAntialiasing() { + return antialiasing; + } + + /** + * Altera a flag de controle da suavização do contexto gráfico. + * + * @param antialiasing O estado da flag. + */ + public void setAntialiasing( boolean antialiasing ) { + this.antialiasing = antialiasing; + } + /** * Rotaciona o contexto gráfico atual a partir da coordenada (0, 0). * Observação: Utilize apenas no método draw! diff --git a/src/br/com/davidbuzatto/jsge/core/utils/ColorUtils.java b/src/br/com/davidbuzatto/jsge/core/utils/ColorUtils.java index feeb04f..93a4853 100644 --- a/src/br/com/davidbuzatto/jsge/core/utils/ColorUtils.java +++ b/src/br/com/davidbuzatto/jsge/core/utils/ColorUtils.java @@ -83,6 +83,32 @@ public static Color colorTint( Color color, Color tint ) { color.getAlpha() * tint.getAlpha() / 255 ); } + + /** + * Gera a cor invertida da cor passada. + * + * @param color A cor. + * @return A cor invertida. + */ + public static Color colorInvert( Color color ) { + return new Color( + 255 - color.getRed(), + 255 - color.getGreen(), + 255 - color.getBlue(), + color.getAlpha() + ); + } + + /** + * Gera a cor em escala de cinza da cor passada. + * + * @param color A cor. + * @return A cor em escala de cinza. + */ + public static Color colorGrayscale( Color color ) { + int gray = ( color.getRed() + color.getGreen() + color.getBlue() ) / 3; + return new Color( gray, gray, gray, color.getAlpha() ); + } /** * Obtém uma cor com correção em relação ao brilho. O fator de brilho vai de diff --git a/src/br/com/davidbuzatto/jsge/examples/JSGEShowcaseWindow.form b/src/br/com/davidbuzatto/jsge/examples/JSGEShowcaseWindow.form index b062297..f8e139a 100644 --- a/src/br/com/davidbuzatto/jsge/examples/JSGEShowcaseWindow.form +++ b/src/br/com/davidbuzatto/jsge/examples/JSGEShowcaseWindow.form @@ -41,6 +41,7 @@ + @@ -60,6 +61,8 @@ + + @@ -124,6 +127,14 @@ + + + + + + + + diff --git a/src/br/com/davidbuzatto/jsge/examples/JSGEShowcaseWindow.java b/src/br/com/davidbuzatto/jsge/examples/JSGEShowcaseWindow.java index 42d282e..04a7992 100644 --- a/src/br/com/davidbuzatto/jsge/examples/JSGEShowcaseWindow.java +++ b/src/br/com/davidbuzatto/jsge/examples/JSGEShowcaseWindow.java @@ -28,6 +28,7 @@ import br.com.davidbuzatto.jsge.examples.basic.UserInteractionExample; import br.com.davidbuzatto.jsge.examples.ball.BouncingBallExample; import br.com.davidbuzatto.jsge.examples.animation.AnimationsExample; +import br.com.davidbuzatto.jsge.examples.basic.CurveSmoothingExample; import br.com.davidbuzatto.jsge.examples.basic.GamepadsExample; import br.com.davidbuzatto.jsge.examples.camera.CameraExample; import br.com.davidbuzatto.jsge.examples.particles.ParticlesExample; @@ -62,6 +63,7 @@ private void initComponents() { btnDrawingPrimitiveObjects = new javax.swing.JButton(); btnPaintingCapabilities = new javax.swing.JButton(); btnCollisionDetection = new javax.swing.JButton(); + btnCurveSmoothing = new javax.swing.JButton(); btnImageLoadingAndProcessing = new javax.swing.JButton(); btnUserInteraction = new javax.swing.JButton(); btnColorMethods = new javax.swing.JButton(); @@ -107,6 +109,13 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { } }); + btnCurveSmoothing.setText("Curve Smoothing"); + btnCurveSmoothing.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCurveSmoothingActionPerformed(evt); + } + }); + btnImageLoadingAndProcessing.setText("Image Loading and Processing"); btnImageLoadingAndProcessing.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -190,7 +199,8 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addComponent(btnSoundAndMusic, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnPaintingCapabilities, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnAnimations, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnGamepads, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(btnGamepads, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnCurveSmoothing, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); layout.setVerticalGroup( @@ -207,6 +217,8 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnCollisionDetection) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCurveSmoothing) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnImageLoadingAndProcessing) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnUserInteraction) @@ -283,6 +295,10 @@ private void btnGamepadsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-F new GamepadsExample().setDefaultCloseOperation( DISPOSE_ON_CLOSE ); }//GEN-LAST:event_btnGamepadsActionPerformed + private void btnCurveSmoothingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCurveSmoothingActionPerformed + new CurveSmoothingExample().setDefaultCloseOperation( DISPOSE_ON_CLOSE ); + }//GEN-LAST:event_btnCurveSmoothingActionPerformed + /** * Executa o Showcase. * @@ -327,6 +343,7 @@ public void run() { private javax.swing.JButton btnCamera; private javax.swing.JButton btnCollisionDetection; private javax.swing.JButton btnColorMethods; + private javax.swing.JButton btnCurveSmoothing; private javax.swing.JButton btnDrawingPrimitiveMethods; private javax.swing.JButton btnDrawingPrimitiveObjects; private javax.swing.JButton btnGamepads; diff --git a/src/br/com/davidbuzatto/jsge/examples/basic/ColorMethodsExample.java b/src/br/com/davidbuzatto/jsge/examples/basic/ColorMethodsExample.java index b1694f7..d254227 100644 --- a/src/br/com/davidbuzatto/jsge/examples/basic/ColorMethodsExample.java +++ b/src/br/com/davidbuzatto/jsge/examples/basic/ColorMethodsExample.java @@ -41,6 +41,7 @@ public ColorMethodsExample() { @Override public void create() { baseColor = LIME; + setDefaultFontSize( 20 ); } @Override @@ -80,13 +81,22 @@ public void draw() { } fillRectangle( 10, 30, 50, 50, baseColor ); + drawText( "base", 70, 50, BLACK ); fillRectangle( 10, 80, 50, 50, ColorUtils.colorAlpha( baseColor, 0.5 ) ); + drawText( "50% alpha", 70, 100, BLACK ); fillRectangle( 10, 130, 50, 50, ColorUtils.colorTint( baseColor, WHITE ) ); - fillRectangle( 10, 180, 50, 50, ColorUtils.colorBrightness( baseColor, -0.5 ) ); - fillRectangle( 10, 230, 50, 50, ColorUtils.colorContrast( baseColor, -0.5 ) ); + drawText( "white tint", 70, 150, BLACK ); + fillRectangle( 10, 180, 50, 50, ColorUtils.colorInvert( baseColor ) ); + drawText( "inverted", 70, 200, BLACK ); + fillRectangle( 10, 230, 50, 50, ColorUtils.colorGrayscale( baseColor ) ); + drawText( "grayscale", 70, 250, BLACK ); + fillRectangle( 10, 280, 50, 50, ColorUtils.colorBrightness( baseColor, -0.5 ) ); + drawText( "-0.5 brightness", 70, 300, BLACK ); + fillRectangle( 10, 330, 50, 50, ColorUtils.colorContrast( baseColor, -0.5 ) ); + drawText( "-0.5 contrast", 70, 350, BLACK ); String message = "right click me ;)"; - drawText( message, 10, getScreenHeight() - 30, 20, BLACK ); + drawText( message, 10, getScreenHeight() - 30, BLACK ); drawHSVCircle(); diff --git a/src/br/com/davidbuzatto/jsge/examples/basic/CurveSmoothingExample.java b/src/br/com/davidbuzatto/jsge/examples/basic/CurveSmoothingExample.java new file mode 100644 index 0000000..ae4e5a7 --- /dev/null +++ b/src/br/com/davidbuzatto/jsge/examples/basic/CurveSmoothingExample.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2024 Prof. Dr. David Buzatto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package br.com.davidbuzatto.jsge.examples.basic; + +import br.com.davidbuzatto.jsge.core.engine.EngineFrame; +import br.com.davidbuzatto.jsge.math.CurveUtils; +import br.com.davidbuzatto.jsge.math.Vector2; +import java.util.ArrayList; +import java.util.List; + +/** + * Exemplo de uso dos métodos de suavização de curvas. + * + * @author Prof. Dr. David Buzatto + */ +public class CurveSmoothingExample extends EngineFrame { + + private List points; + private List smoothChaikin; + private List smoothCatmullRom; + private boolean pointsChanged; + + private double tension; + private int iterations; + + /** + * Cria o exemplo. + */ + public CurveSmoothingExample() { + super( 600, 600, "Curve Smoothing", 60, true ); + } + + @Override + public void create() { + points = new ArrayList<>(); + smoothChaikin = new ArrayList<>(); + smoothCatmullRom = new ArrayList<>(); + tension = 0; + iterations = 1; + setDefaultFontSize( 20 ); + setDefaultStrokeLineWidth( 2 ); + } + + @Override + public void update( double delta ) { + + if ( isKeyPressed( KEY_UP ) ) { + tension += 0.05; + pointsChanged = true; + } else if ( isKeyPressed( KEY_DOWN ) ) { + tension -= 0.05; + pointsChanged = true; + } + + if ( tension < 0 ) { + tension = 0; + pointsChanged = false; + } else if ( tension > 1 ) { + tension = 1; + pointsChanged = false; + } + + if ( isKeyPressed( KEY_LEFT ) ) { + iterations--; + pointsChanged = true; + } else if ( isKeyPressed( KEY_RIGHT ) ) { + iterations++; + pointsChanged = true; + } + + if ( iterations < 1 ) { + iterations = 1; + pointsChanged = false; + } else if ( iterations > 10 ) { + iterations = 10; + pointsChanged = false; + } + + if ( isMouseButtonPressed( MOUSE_BUTTON_LEFT ) ) { + points.add( getMousePositionPoint() ); + pointsChanged = true; + } + + if ( pointsChanged ) { + smoothChaikin = CurveUtils.getCurveSmoothingChaikin( points, tension, iterations ); + smoothCatmullRom = CurveUtils.getSplineInterpolationCatmullRom( points, iterations ); + pointsChanged = false; + } + + } + + @Override + public void draw() { + + clearBackground( WHITE ); + + setStrokeLineWidth( 1 ); + for ( Vector2 point : points ) { + drawCircle( point, 5, RED ); + } + + setStrokeDashArray( new float[]{ 4, 4 } ); + for ( int i = 0; i < points.size() - 1; i++ ) { + drawLine( points.get( i ), points.get( i + 1 ), BLACK ); + } + + setStrokeLineWidth( 4 ); + setStrokeDashArray( null ); + for ( int i = 0; i < smoothChaikin.size() - 1; i++ ) { + drawLine( smoothChaikin.get( i ), smoothChaikin.get( i + 1 ), BLUE ); + } + + for ( int i = 0; i < smoothCatmullRom.size() - 1; i++ ) { + drawLine( smoothCatmullRom.get( i ), smoothCatmullRom.get( i + 1 ), ORANGE ); + } + + drawFPS( 10, 10 ); + + + drawText( "Draw a curve by clicking with the mouse!", 115, 10, BLACK ); + drawText( "Chaikin", getScreenWidth() - measureText( "Chaikin" ) - 10, getScreenHeight() - 50, BLUE ); + drawText( "Catmull-Rom", getScreenWidth() - measureText( "Catmull-Rom" ) - 10, getScreenHeight() - 30, ORANGE ); + + drawText( String.format( "tension: %.2f (UP/DOWN)", tension ), 10, getScreenHeight() - 50, BLACK ); + drawText( String.format( "iterations: %d (LEFT/RIGHT)", iterations ), 10, getScreenHeight() - 30, BLACK ); + + + } + + /** + * Executa o exemplo. + * @param args Argumentos. + */ + public static void main( String[] args ) { + new CurveSmoothingExample(); + } + +} diff --git a/src/br/com/davidbuzatto/jsge/geom/Arc.java b/src/br/com/davidbuzatto/jsge/geom/Arc.java index e7e1612..192421a 100644 --- a/src/br/com/davidbuzatto/jsge/geom/Arc.java +++ b/src/br/com/davidbuzatto/jsge/geom/Arc.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de um arco em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class Arc implements Drawable { +public class Arc implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do centro. diff --git a/src/br/com/davidbuzatto/jsge/geom/Circle.java b/src/br/com/davidbuzatto/jsge/geom/Circle.java index 00f2c7d..6535106 100644 --- a/src/br/com/davidbuzatto/jsge/geom/Circle.java +++ b/src/br/com/davidbuzatto/jsge/geom/Circle.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de um círculo em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class Circle implements Drawable { +public class Circle implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do centro. diff --git a/src/br/com/davidbuzatto/jsge/geom/CircleSector.java b/src/br/com/davidbuzatto/jsge/geom/CircleSector.java index ab4797d..e544ac1 100644 --- a/src/br/com/davidbuzatto/jsge/geom/CircleSector.java +++ b/src/br/com/davidbuzatto/jsge/geom/CircleSector.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de um setor circular. * * @author Prof. Dr. David Buzatto */ -public class CircleSector implements Drawable { +public class CircleSector implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do centro. diff --git a/src/br/com/davidbuzatto/jsge/geom/CubicCurve.java b/src/br/com/davidbuzatto/jsge/geom/CubicCurve.java index 2d84205..123ad7d 100644 --- a/src/br/com/davidbuzatto/jsge/geom/CubicCurve.java +++ b/src/br/com/davidbuzatto/jsge/geom/CubicCurve.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de uma curva Bézier cúbica. * * @author Prof. Dr. David Buzatto */ -public class CubicCurve implements Drawable { +public class CubicCurve implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do ponto inicial. diff --git a/src/br/com/davidbuzatto/jsge/geom/Ellipse.java b/src/br/com/davidbuzatto/jsge/geom/Ellipse.java index 76a878d..d0d124c 100644 --- a/src/br/com/davidbuzatto/jsge/geom/Ellipse.java +++ b/src/br/com/davidbuzatto/jsge/geom/Ellipse.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de uma elipse em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class Ellipse implements Drawable { +public class Ellipse implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do centro. diff --git a/src/br/com/davidbuzatto/jsge/geom/EllipseSector.java b/src/br/com/davidbuzatto/jsge/geom/EllipseSector.java index 157af6f..1ca73b1 100644 --- a/src/br/com/davidbuzatto/jsge/geom/EllipseSector.java +++ b/src/br/com/davidbuzatto/jsge/geom/EllipseSector.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de um arco em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class EllipseSector implements Drawable { +public class EllipseSector implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do centro. diff --git a/src/br/com/davidbuzatto/jsge/geom/Line.java b/src/br/com/davidbuzatto/jsge/geom/Line.java index 17aeda7..73c519d 100644 --- a/src/br/com/davidbuzatto/jsge/geom/Line.java +++ b/src/br/com/davidbuzatto/jsge/geom/Line.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de uma linha em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class Line implements Drawable { +public class Line implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do ponto inicial. diff --git a/src/br/com/davidbuzatto/jsge/geom/Path.java b/src/br/com/davidbuzatto/jsge/geom/Path.java index d9f56fa..a3cff66 100644 --- a/src/br/com/davidbuzatto/jsge/geom/Path.java +++ b/src/br/com/davidbuzatto/jsge/geom/Path.java @@ -20,13 +20,16 @@ import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; import java.awt.geom.Path2D; +import java.io.Serializable; /** * Classe para representação de um caminho em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class Path implements Drawable { +public class Path implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Path2D desse caminho. diff --git a/src/br/com/davidbuzatto/jsge/geom/Polygon.java b/src/br/com/davidbuzatto/jsge/geom/Polygon.java index 776ad68..5179c7e 100644 --- a/src/br/com/davidbuzatto/jsge/geom/Polygon.java +++ b/src/br/com/davidbuzatto/jsge/geom/Polygon.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de um polígono regular em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class Polygon implements Drawable { +public class Polygon implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do centro. diff --git a/src/br/com/davidbuzatto/jsge/geom/QuadCurve.java b/src/br/com/davidbuzatto/jsge/geom/QuadCurve.java index b6f9281..6dac537 100644 --- a/src/br/com/davidbuzatto/jsge/geom/QuadCurve.java +++ b/src/br/com/davidbuzatto/jsge/geom/QuadCurve.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de uma curva Bézier quadrática. * * @author Prof. Dr. David Buzatto */ -public class QuadCurve implements Drawable { +public class QuadCurve implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do ponto inicial. diff --git a/src/br/com/davidbuzatto/jsge/geom/Rectangle.java b/src/br/com/davidbuzatto/jsge/geom/Rectangle.java index bc5761b..54d2e75 100644 --- a/src/br/com/davidbuzatto/jsge/geom/Rectangle.java +++ b/src/br/com/davidbuzatto/jsge/geom/Rectangle.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de um retângulo em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class Rectangle implements Drawable { +public class Rectangle implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do vértice superior esquerdo. diff --git a/src/br/com/davidbuzatto/jsge/geom/Ring.java b/src/br/com/davidbuzatto/jsge/geom/Ring.java index 4524520..e670e47 100644 --- a/src/br/com/davidbuzatto/jsge/geom/Ring.java +++ b/src/br/com/davidbuzatto/jsge/geom/Ring.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de um anel em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class Ring implements Drawable { +public class Ring implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do centro. diff --git a/src/br/com/davidbuzatto/jsge/geom/RoundRectangle.java b/src/br/com/davidbuzatto/jsge/geom/RoundRectangle.java index 6c1c2a3..1cb3e0e 100644 --- a/src/br/com/davidbuzatto/jsge/geom/RoundRectangle.java +++ b/src/br/com/davidbuzatto/jsge/geom/RoundRectangle.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de um retângulo com cantos arrendondados em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class RoundRectangle implements Drawable { +public class RoundRectangle implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do vértice superior esquerdo. diff --git a/src/br/com/davidbuzatto/jsge/geom/Star.java b/src/br/com/davidbuzatto/jsge/geom/Star.java index a777123..48cb757 100644 --- a/src/br/com/davidbuzatto/jsge/geom/Star.java +++ b/src/br/com/davidbuzatto/jsge/geom/Star.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de um estrela em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class Star implements Drawable { +public class Star implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do centro. diff --git a/src/br/com/davidbuzatto/jsge/geom/Triangle.java b/src/br/com/davidbuzatto/jsge/geom/Triangle.java index 6423db2..35f2161 100644 --- a/src/br/com/davidbuzatto/jsge/geom/Triangle.java +++ b/src/br/com/davidbuzatto/jsge/geom/Triangle.java @@ -19,13 +19,16 @@ import br.com.davidbuzatto.jsge.core.Drawable; import br.com.davidbuzatto.jsge.core.engine.EngineFrame; import java.awt.Paint; +import java.io.Serializable; /** * Classe para representação de um triângulo em duas dimensões. * * @author Prof. Dr. David Buzatto */ -public class Triangle implements Drawable { +public class Triangle implements Drawable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x do primeiro vértice. diff --git a/src/br/com/davidbuzatto/jsge/math/CurveUtils.java b/src/br/com/davidbuzatto/jsge/math/CurveUtils.java index ff3ccbf..6f575f6 100644 --- a/src/br/com/davidbuzatto/jsge/math/CurveUtils.java +++ b/src/br/com/davidbuzatto/jsge/math/CurveUtils.java @@ -19,6 +19,8 @@ import br.com.davidbuzatto.jsge.geom.CubicCurve; import br.com.davidbuzatto.jsge.geom.Line; import br.com.davidbuzatto.jsge.geom.QuadCurve; +import java.util.ArrayList; +import java.util.List; /** * Interface com métodos utilitários para curvas. @@ -171,4 +173,175 @@ public static Vector2 getPointAtCubicCurve( CubicCurve cubicCurve, double amount return getPointAtCubicCurve( cubicCurve.x1, cubicCurve.y1, cubicCurve.c1x, cubicCurve.c1y, cubicCurve.c2x, cubicCurve.c2y, cubicCurve.x2, cubicCurve.y2, amount ); } + /** + * Aplica o algoritmo de Chaikin em uma curva representada por uma lista de + * pontos, retornando uma nova lista de pontos que corresponde à curva + * suavizada. + * + * Referências: + * https://www.codeproject.com/Articles/1093960/2D-Polyline-Vertex-Smoothing + * https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + * + * @param points Pontos que serão processados. + * @param tension Tensão [0..1] + * @param iterations Quantidade iterações [1..10] + * @return Uma lista de pontos que representa uma curva suavizada ou uma + * lista vazia caso a lista de pontos contenha menos que 3 pontos. + */ + public static List getCurveSmoothingChaikin( List points, double tension, int iterations ) { + + List newList = new ArrayList<>(); + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // checks + if ( points == null || points.size() < 3 ) { + return newList; + } + + if ( iterations < 1 ) { + iterations = 1; + } else if ( iterations > 10 ) { + iterations = 10; + } + + if ( tension < 0 ) { + tension = 0; + } else if ( tension > 1 ) { + tension = 1; + } + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // the tension factor defines a scale between corner cutting distance in segment half length, i.e. between 0.05 and 0.45 + // the opposite corner will be cut by the inverse (i.e. 1-cutting distance) to keep symmetry + // with a tension value of 0.5 this amounts to 0.25 = 1/4 and 0.75 = 3/4 the original Chaikin values + double cutdist = 0.05 + ( tension * 0.4 ); + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // make a copy of the pointlist and feed it to the iteration + for ( Vector2 point : points ) { + newList.add( new Vector2( point.x, point.y ) ); + } + + for ( int i = 0; i <= iterations; i++ ) { + newList = getSmootherChaikin( newList, cutdist ); + } + + return newList; + + } + + private static List getSmootherChaikin( List points, double cuttingDist ) { + + List newList = new ArrayList<>(); + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // always add the first point + newList.add( new Vector2( points.get( 0 ).x, points.get( 0 ).y ) ); + + for ( int i = 0; i < points.size() - 1; i++ ) { + + Vector2 p1 = points.get( i ); + Vector2 p2 = points.get( i + 1 ); + + Vector2 q = new Vector2( + ( 1 - cuttingDist ) * p1.x + cuttingDist * p2.x, + ( 1 - cuttingDist ) * p1.y + cuttingDist * p2.y + ); + + Vector2 r = new Vector2( + cuttingDist * p1.x + ( 1 - cuttingDist ) * p2.x, + cuttingDist * p1.y + ( 1 - cuttingDist ) * p2.y + ); + + newList.add( q ); + newList.add( r ); + + } + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // always add the last point + newList.add( new Vector2( points.get( points.size() - 1 ).x, points.get( points.size() - 1 ).y ) ); + + return newList; + + } + + /** + * Aplica o algoritmo de Catmull-Rom em uma curva representada por uma lista de + * pontos, retornando uma nova lista de pontos que corresponde à curva + * suavizada. + * + * @param points A lista de pontos. + * @param interpolationPoints A quantidade de pontos de interpolação. + * @return Uma lista de pontos que representa uma curva suavizada ou uma + * lista vazia caso a lista de pontos contenha menos que 3 pontos. + */ + public static List getSplineInterpolationCatmullRom( List points, int interpolationPoints ) { + + List spline = new ArrayList<>(); + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // The Catmull-Rom Spline, requires at least 4 points so it is possible to extrapolate from 3 points, but not from 2. + // you would get a straight line anyway + if ( points.size() < 3 ) { + return spline; + } + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // could throw an error on the following, but it is easily fixed implicitly + if ( interpolationPoints < 1 ) { + interpolationPoints = 1; + } + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // create a new pointlist to do splining on + // if you don't do this, the original pointlist gets extended with the exptrapolated points + List spoints = new ArrayList<>(); + for( Vector2 p : points ) { + spoints.add( new Vector2( p.x, p.y ) ); + } + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // always extrapolate the first and last point out + double dx = spoints.get(1).x - spoints.get(0).x; + double dy = spoints.get(1).y - spoints.get(0).y; + spoints.add( 0, new Vector2( spoints.get(0).x - dx, spoints.get(0).y - dy ) ); + dx = spoints.get(spoints.size()-1).x - spoints.get(spoints.size()-2).x; + dy = spoints.get(spoints.size()-1).y - spoints.get(spoints.size()-2).y; + spoints.add( new Vector2( spoints.get(spoints.size()-1).x + dx, spoints.get(spoints.size()-1).y + dy ) ); + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // Note the nrOfInterpolatedPoints acts as a kind of tension factor between 0 and 1 because it is normalised + // to 1/nrOfInterpolatedPoints. It can never be 0 + double t; + Vector2 spoint; + + for ( int i = 0; i <= spoints.size() - 4; i++ ) { + + for ( int intp = 0; intp <= interpolationPoints - 1; intp++ ) { + + t = 1.0 / interpolationPoints * intp; + Vector2 i0 = spoints.get( i ); + Vector2 i1 = spoints.get( i + 1 ); + Vector2 i2 = spoints.get( i + 2 ); + Vector2 i3 = spoints.get( i + 3 ); + double t2 = t * t; + double t3 = t2 * t; + + spline.add( new Vector2( + 0.5 * ( 2 * i1.x + ( -1 * i0.x + i2.x ) * t + ( 2 * i0.x - 5 * i1.x + 4 * i2.x - i3.x ) * t2 + ( -1 * i0.x + 3 * i1.x - 3 * i2.x + i3.x ) * t3 ), + 0.5 * ( 2 * i1.y + ( -1 * i0.y + i2.y ) * t + ( 2 * i0.y - 5 * i1.y + 4 * i2.y - i3.y ) * t2 + ( -1 * i0.y + 3 * i1.y - 3 * i2.y + i3.y ) * t3 ) + )); + + } + + } + + // comentário original: https://github.com/xstos/PolylineSmoothCSharp/blob/master/MainForm.cs + // add the last point, but skip the interpolated last point, so second last... + spline.add( spoints.get(spoints.size() - 2) ); + return spline; + + } + } diff --git a/src/br/com/davidbuzatto/jsge/math/Matrix.java b/src/br/com/davidbuzatto/jsge/math/Matrix.java index 6c6d166..eecd72c 100644 --- a/src/br/com/davidbuzatto/jsge/math/Matrix.java +++ b/src/br/com/davidbuzatto/jsge/math/Matrix.java @@ -16,12 +16,16 @@ */ package br.com.davidbuzatto.jsge.math; +import java.io.Serializable; + /** * Uma matriz. * * @author Prof. Dr. David Buzatto */ -public class Matrix implements Cloneable { +public class Matrix implements Cloneable, Serializable { + + private static final long serialVersionUID = 1L; /** Linha 1, coluna 1 */ public double m0; diff --git a/src/br/com/davidbuzatto/jsge/math/Quaternion.java b/src/br/com/davidbuzatto/jsge/math/Quaternion.java index f113039..ce170bd 100644 --- a/src/br/com/davidbuzatto/jsge/math/Quaternion.java +++ b/src/br/com/davidbuzatto/jsge/math/Quaternion.java @@ -16,12 +16,16 @@ */ package br.com.davidbuzatto.jsge.math; +import java.io.Serializable; + /** * Classe para representação de um quatérnio. * * @author Prof. Dr. David Buzatto */ -public class Quaternion implements Cloneable { +public class Quaternion implements Cloneable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x. diff --git a/src/br/com/davidbuzatto/jsge/math/Vector2.java b/src/br/com/davidbuzatto/jsge/math/Vector2.java index a11ef9d..a6e12bb 100644 --- a/src/br/com/davidbuzatto/jsge/math/Vector2.java +++ b/src/br/com/davidbuzatto/jsge/math/Vector2.java @@ -16,13 +16,17 @@ */ package br.com.davidbuzatto.jsge.math; +import java.io.Serializable; + /** * Classe para representação de um vetor de duas dimensões. * Também é usada para representar pontos 2D em várias partes da API da Engine. * * @author Prof. Dr. David Buzatto */ -public class Vector2 implements Cloneable { +public class Vector2 implements Cloneable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x. diff --git a/src/br/com/davidbuzatto/jsge/math/Vector3.java b/src/br/com/davidbuzatto/jsge/math/Vector3.java index 7bfa1e8..c6d5ea0 100644 --- a/src/br/com/davidbuzatto/jsge/math/Vector3.java +++ b/src/br/com/davidbuzatto/jsge/math/Vector3.java @@ -16,6 +16,8 @@ */ package br.com.davidbuzatto.jsge.math; +import java.io.Serializable; + /** * Classe para representação de um vetor de três dimensões. * @@ -24,7 +26,9 @@ * * @author Prof. Dr. David Buzatto */ -public class Vector3 implements Cloneable { +public class Vector3 implements Cloneable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x. diff --git a/src/br/com/davidbuzatto/jsge/math/Vector4.java b/src/br/com/davidbuzatto/jsge/math/Vector4.java index 86d2bce..d59f5ec 100644 --- a/src/br/com/davidbuzatto/jsge/math/Vector4.java +++ b/src/br/com/davidbuzatto/jsge/math/Vector4.java @@ -16,6 +16,8 @@ */ package br.com.davidbuzatto.jsge.math; +import java.io.Serializable; + /** * Classe para representação de um vetor de quatro dimensões. * @@ -23,7 +25,9 @@ * * @author Prof. Dr. David Buzatto */ -public class Vector4 implements Cloneable { +public class Vector4 implements Cloneable, Serializable { + + private static final long serialVersionUID = 1L; /** * Coordenada x.