Initial Commit
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
|
||||
eclipse.project.name = appName + '-core'
|
||||
|
||||
dependencies {
|
||||
api "com.badlogicgames.gdx:gdx:$gdxVersion"
|
||||
api "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package io.doppelspalt;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
import com.badlogic.gdx.utils.viewport.FitViewport;
|
||||
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
|
||||
public class DoppelspaltSimulation implements Screen {
|
||||
|
||||
private final Main app;
|
||||
private OrthographicCamera camera;
|
||||
private Viewport viewport;
|
||||
private ShapeRenderer shapeRenderer;
|
||||
|
||||
// Physikalische Parameter
|
||||
private static final float WAVELENGTH = 550e-9f; // Wellenlänge in Metern
|
||||
private static final float SLIT_DISTANCE = 0.0002f; // Abstand zwischen den Spalten
|
||||
private static final float SLIT_WIDTH = 0.00005f; // Breite eines Spalts
|
||||
private static final float SCREEN_DISTANCE = 1.0f; // Abstand zur Projektionsfläche
|
||||
|
||||
private final int screenPixelWidth = 1280;
|
||||
private final int screenPixelHeight = 720;
|
||||
|
||||
public DoppelspaltSimulation(Main app) {
|
||||
this.app = app;
|
||||
camera = new OrthographicCamera();
|
||||
viewport = new FitViewport(screenPixelWidth, screenPixelHeight, camera);
|
||||
shapeRenderer = new ShapeRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {}
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
Gdx.gl.glClearColor(0, 0, 0.05f, 1);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
camera.update();
|
||||
shapeRenderer.setProjectionMatrix(camera.combined);
|
||||
|
||||
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
|
||||
renderInterferencePattern();
|
||||
shapeRenderer.end();
|
||||
}
|
||||
|
||||
private void renderInterferencePattern() {
|
||||
float screenCenterY = screenPixelHeight / 2f;
|
||||
float scale = 1e6f; // Maßstab für Umrechnung von Metern zu Pixeln
|
||||
|
||||
for (int x = 0; x < screenPixelWidth; x++) {
|
||||
// Umrechnung der x-Position in Meter (relativ zur Mitte)
|
||||
float screenX = ((float) x / screenPixelWidth - 0.5f);
|
||||
float position = screenX * 0.01f; // ca. ±0.005 m auf dem Schirm
|
||||
|
||||
// Berechne Gangunterschied Δs = d * sin(θ) ≈ d * tan(θ) = d * y / L
|
||||
float deltaS = SLIT_DISTANCE * position / SCREEN_DISTANCE;
|
||||
|
||||
// Interferenz: I ∝ cos²(π Δs / λ)
|
||||
float intensity = (float) Math.pow(Math.cos(Math.PI * deltaS / WAVELENGTH), 2);
|
||||
|
||||
// Diffraction envelope (Einzelspalt)
|
||||
float beta = (float) ((Math.PI * SLIT_WIDTH * position) / (WAVELENGTH * SCREEN_DISTANCE));
|
||||
float envelope = beta != 0 ? (float) Math.pow(Math.sin(beta) / beta, 2) : 1f;
|
||||
|
||||
float totalIntensity = intensity * envelope;
|
||||
|
||||
// Zeichne vertikale Linie proportional zur Intensität
|
||||
float lineHeight = totalIntensity * screenPixelHeight;
|
||||
float y = screenCenterY - lineHeight / 2f;
|
||||
|
||||
shapeRenderer.setColor(totalIntensity, totalIntensity, totalIntensity, 1);
|
||||
shapeRenderer.rect(x, y, 1, lineHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height) {
|
||||
viewport.update(width, height, true);
|
||||
}
|
||||
|
||||
@Override public void pause() {}
|
||||
@Override public void resume() {}
|
||||
@Override public void hide() {}
|
||||
@Override public void dispose() {
|
||||
shapeRenderer.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.doppelspalt;
|
||||
|
||||
import com.badlogic.gdx.Screen;
|
||||
|
||||
/** First screen of the application. Displayed after the application is created. */
|
||||
public class FirstScreen implements Screen {
|
||||
@Override
|
||||
public void show() {
|
||||
// Prepare your screen here.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
// Draw your screen here. "delta" is the time since last render in seconds.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height) {
|
||||
// Resize your screen here. The parameters represent the new window size.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
// Invoked when your application is paused.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
// Invoked when your application is resumed after pause.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
// This method is called when another screen replaces this one.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
// Destroy screen's assets here.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
package io.doppelspalt;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.*;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
|
||||
public class FullscreenButton extends ImageButton {
|
||||
private ImageButton fullscreenButton;
|
||||
private boolean isFullscreen;
|
||||
private Stage stage;
|
||||
private Skin skin;
|
||||
private int FULL_BUTTON_SIZE = 50;
|
||||
|
||||
public FullscreenButton(Stage stage, Skin skin) {
|
||||
super(skin);
|
||||
this.stage = stage;
|
||||
this.skin = skin;
|
||||
this.isFullscreen = false;
|
||||
|
||||
// Statt Icons verwenden wir jetzt farbige Rechtecke aus der Skin:
|
||||
ImageButton.ImageButtonStyle style = new ImageButton.ImageButtonStyle();
|
||||
style.imageUp = skin.newDrawable("rect", Color.RED); // sichtbar in Rot
|
||||
style.imageDown = skin.newDrawable("rect", Color.DARK_GRAY); // beim Drücken dunkelgrau
|
||||
|
||||
fullscreenButton = new ImageButton(style);
|
||||
fullscreenButton.addListener(new TextTooltip("Toggle fullscreen", skin));
|
||||
|
||||
|
||||
// Sichtbar positionieren:
|
||||
fullscreenButton.setSize(100, 100);
|
||||
fullscreenButton.setPosition(10, 10);
|
||||
|
||||
fullscreenButton.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
toggleFullscreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addToStage(Stage stage) {
|
||||
stage.addActor(fullscreenButton);
|
||||
}
|
||||
|
||||
private void toggleFullscreen() {
|
||||
if (isFullscreen) {
|
||||
Gdx.graphics.setWindowedMode(1920, 1080);
|
||||
} else {
|
||||
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
|
||||
}
|
||||
isFullscreen = !isFullscreen;
|
||||
// Icon-Update entfällt hier, da wir keine Icons verwenden
|
||||
}
|
||||
|
||||
public void toFront() {
|
||||
fullscreenButton.toFront();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
// keine Texturen zum Entsorgen
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
package io.doppelspalt;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.*;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.*;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.*;
|
||||
|
||||
public class FullscreenButton extends Button {
|
||||
private ImageButton fullscreenButton;
|
||||
private boolean isFullscreen;
|
||||
private Stage stage;
|
||||
private Skin skin;
|
||||
private Texture fullscreenIcon;
|
||||
private Texture windowedIcon;
|
||||
private static int FULL_BUTTON_SIZE = 50;
|
||||
|
||||
public FullscreenButton(Stage stage, Skin skin) {
|
||||
super(skin);
|
||||
this.stage = stage;
|
||||
this.skin = skin;
|
||||
this.isFullscreen = false;
|
||||
|
||||
windowedIcon = new Texture(Gdx.files.internal("windowed-1.png"));
|
||||
fullscreenIcon = new Texture(Gdx.files.internal("fullscreen-1.png"));
|
||||
|
||||
|
||||
ImageButton.ImageButtonStyle style = new ImageButton.ImageButtonStyle();
|
||||
style.imageUp = new TextureRegionDrawable(new TextureRegion(fullscreenIcon));
|
||||
style.imageDown = new TextureRegionDrawable(new TextureRegion(fullscreenIcon));
|
||||
|
||||
fullscreenButton = new ImageButton(style);
|
||||
fullscreenButton.addListener(new TextTooltip("Toggle fullscreen", skin));
|
||||
|
||||
|
||||
fullscreenButton.setSize(FULL_BUTTON_SIZE, FULL_BUTTON_SIZE);
|
||||
fullscreenButton.setPosition(0, 0);
|
||||
|
||||
fullscreenButton.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
toggleFullscreen();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void addToStage(Stage stage) {
|
||||
stage.addActor(fullscreenButton);
|
||||
}
|
||||
|
||||
private void toggleFullscreen() {
|
||||
if (isFullscreen) {
|
||||
Gdx.graphics.setWindowedMode(1920, 1080);
|
||||
} else {
|
||||
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
|
||||
}
|
||||
|
||||
isFullscreen = !isFullscreen;
|
||||
updateButtonIcon();
|
||||
}
|
||||
|
||||
private void updateButtonIcon() {
|
||||
Texture newTexture = isFullscreen ? windowedIcon : fullscreenIcon;
|
||||
((TextureRegionDrawable) fullscreenButton.getStyle().imageUp).setRegion(new TextureRegion(newTexture));
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
fullscreenIcon.dispose();
|
||||
windowedIcon.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public class FullscreenButton extends ImageButton {
|
||||
private boolean isFullscreen;
|
||||
private Texture fullscreenIcon;
|
||||
private Texture windowedIcon;
|
||||
private static final int FULL_BUTTON_SIZE = 50;
|
||||
|
||||
public FullscreenButton(Stage stage, Skin skin) {
|
||||
super(createStyle(skin));
|
||||
this.isFullscreen = false;
|
||||
|
||||
windowedIcon = new Texture(Gdx.files.internal("windowed-1.png"));
|
||||
fullscreenIcon = new Texture(Gdx.files.internal("fullscreen-1.png"));
|
||||
|
||||
setSize(FULL_BUTTON_SIZE, FULL_BUTTON_SIZE);
|
||||
|
||||
addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
toggleFullscreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static ImageButtonStyle createStyle(Skin skin) {
|
||||
Texture fullscreenIcon = new Texture(Gdx.files.internal("fullscreen-1.png"));
|
||||
ImageButtonStyle style = new ImageButtonStyle();
|
||||
style.imageUp = new TextureRegionDrawable(new TextureRegion(fullscreenIcon));
|
||||
style.imageDown = new TextureRegionDrawable(new TextureRegion(fullscreenIcon));
|
||||
return style;
|
||||
}
|
||||
|
||||
private void toggleFullscreen() {
|
||||
if (isFullscreen) {
|
||||
Gdx.graphics.setWindowedMode(1920, 1080);
|
||||
} else {
|
||||
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
|
||||
}
|
||||
isFullscreen = !isFullscreen;
|
||||
updateButtonIcon();
|
||||
}
|
||||
|
||||
private void updateButtonIcon() {
|
||||
Texture newTexture = isFullscreen ? windowedIcon : fullscreenIcon;
|
||||
((TextureRegionDrawable)getStyle().imageUp).setRegion(new TextureRegion(newTexture));
|
||||
((TextureRegionDrawable)getStyle().imageDown).setRegion(new TextureRegion(newTexture));
|
||||
}
|
||||
|
||||
|
||||
public void addToStage(Stage stage) {
|
||||
stage.addActor(this);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
fullscreenIcon.dispose();
|
||||
windowedIcon.dispose();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.10.0//EN" "https://www.gwtproject.org/doctype/2.10.0/gwt-module.dtd">
|
||||
<module>
|
||||
<source path="" />
|
||||
|
||||
</module>
|
||||
@@ -0,0 +1,445 @@
|
||||
package io.doppelspalt;
|
||||
|
||||
import com.badlogic.gdx.ApplicationListener;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
||||
|
||||
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||
import com.badlogic.gdx.utils.viewport.FitViewport;
|
||||
import com.badlogic.gdx.utils.viewport.ScreenViewport;
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
|
||||
public class Main implements ApplicationListener {
|
||||
|
||||
private Viewport viewport;
|
||||
private OrthographicCamera camera;
|
||||
private ShapeRenderer shapeRenderer;
|
||||
private BitmapFont font;
|
||||
|
||||
private Stage stage;
|
||||
private Skin skin;
|
||||
private Table table;
|
||||
|
||||
private int lambda = 50;
|
||||
private int gitterD = 75;
|
||||
private int winkel = 90;
|
||||
|
||||
private Label fpsLabel;
|
||||
private Slider lambdaSlider, dSlider, winkelSlider;
|
||||
private Label ratioLabel;
|
||||
|
||||
private FullscreenButton fullButton;
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
font = new BitmapFont(Gdx.files.internal("bitmap/c059.fnt"));
|
||||
|
||||
camera = new OrthographicCamera();
|
||||
table = new Table();
|
||||
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
|
||||
shapeRenderer = new ShapeRenderer();
|
||||
|
||||
//viewport = new FitViewport(1920, 1080, camera);
|
||||
viewport = new ScreenViewport();
|
||||
stage = new Stage(viewport);
|
||||
Gdx.input.setInputProcessor(stage);
|
||||
|
||||
skin = new Skin(Gdx.files.internal("ui/uiskin.json"));
|
||||
|
||||
fullButton = new FullscreenButton(stage, skin);
|
||||
setupUI();
|
||||
}
|
||||
|
||||
private void setupUI() {
|
||||
lambdaSlider = new Slider(10, 85, 1, false, skin);
|
||||
dSlider = new Slider(0, 150, 1, false, skin);
|
||||
winkelSlider = new Slider(0, 180, 1, false, skin);
|
||||
|
||||
lambdaSlider.setValue(lambda);
|
||||
dSlider.setValue(gitterD);
|
||||
winkelSlider.setValue(winkel);
|
||||
|
||||
Label.LabelStyle style = new Label.LabelStyle(skin.getFont("font"), Color.BLACK);
|
||||
style.font = font;
|
||||
|
||||
ratioLabel = new Label("d/lambda = " + formatRatio(), style);
|
||||
|
||||
lambdaSlider.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
lambda = (int) lambdaSlider.getValue();
|
||||
updateRatio();
|
||||
}
|
||||
});
|
||||
|
||||
dSlider.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
gitterD = (int) dSlider.getValue();
|
||||
updateRatio();
|
||||
}
|
||||
});
|
||||
|
||||
winkelSlider.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
winkel = (int) winkelSlider.getValue();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
table.top().left();
|
||||
table.pack();
|
||||
|
||||
table.setPosition(10, viewport.getWorldHeight() - 10);
|
||||
|
||||
if (viewport.getWorldHeight() > viewport.getWorldWidth()) {
|
||||
table.setWidth(viewport.getWorldWidth() - 20);
|
||||
}
|
||||
|
||||
fpsLabel = new Label("FPS: 0", style);
|
||||
|
||||
//table.row();
|
||||
//table.add(fpsLabel).left().colspan(2).padTop(10);
|
||||
//table.row();
|
||||
|
||||
|
||||
|
||||
Label lambdaLabel = new Label("Lambda", style);
|
||||
table.add(lambdaLabel).left().pad(5);
|
||||
|
||||
table.add(lambdaSlider).width(300).pad(5);
|
||||
table.row();
|
||||
|
||||
//Label dLabel = new Label("Slit distance d", style);
|
||||
Label dLabel = new Label("D", style);
|
||||
table.add(dLabel).left().pad(5);
|
||||
|
||||
table.add(dSlider).width(300).pad(5);
|
||||
table.row();
|
||||
|
||||
//Label winkelLabel = new Label("Angle of incidence", style);
|
||||
Label winkelLabel = new Label("Winkel", style);
|
||||
table.add(winkelLabel).left().pad(5);
|
||||
|
||||
table.add(winkelSlider).width(300).pad(5);
|
||||
table.row();
|
||||
|
||||
table.add(ratioLabel).colspan(2).padTop(10);
|
||||
table.row();
|
||||
|
||||
TextButton resetButton = new TextButton("Reset", skin);
|
||||
resetButton.setSize(10, 10);
|
||||
resetButton.addListener(new ChangeListener() {
|
||||
@Override
|
||||
public void changed(ChangeEvent event, Actor actor) {
|
||||
lambdaSlider.setValue(50);
|
||||
dSlider.setValue(75);
|
||||
winkelSlider.setValue(90);
|
||||
|
||||
lambda = 50;
|
||||
gitterD = 75;
|
||||
winkel = 90;
|
||||
|
||||
updateRatio();
|
||||
}
|
||||
});
|
||||
|
||||
table.add(resetButton)
|
||||
.colspan(2)
|
||||
.padTop(10)
|
||||
.width(100)
|
||||
.height(30);
|
||||
table.row();
|
||||
|
||||
|
||||
stage.addActor(table);
|
||||
//stage.setDebugAll(true);
|
||||
|
||||
|
||||
|
||||
//fullButton.addToStage(stage);
|
||||
//fullButton.toFront();
|
||||
}
|
||||
|
||||
private void updateRatio() {
|
||||
ratioLabel.setText("d/lambda = " + formatRatio());
|
||||
}
|
||||
|
||||
|
||||
private String formatRatio() {
|
||||
double value = (double) gitterD / lambda;
|
||||
return formatDouble(value, 2);
|
||||
}
|
||||
|
||||
private String formatDouble(double value, int decimals) {
|
||||
double scale = Math.pow(10, decimals);
|
||||
return String.valueOf(Math.round(value * scale) / scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
float delta = Gdx.graphics.getDeltaTime();
|
||||
Gdx.gl.glClearColor(1, 1, 1, 1);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
fpsLabel.setText("FPS: " + Gdx.graphics.getFramesPerSecond());
|
||||
|
||||
camera.update();
|
||||
shapeRenderer.setProjectionMatrix(camera.combined);
|
||||
|
||||
drawInterference();
|
||||
|
||||
stage.act(delta);
|
||||
stage.draw();
|
||||
}
|
||||
|
||||
private void drawInterference() {
|
||||
int width = Gdx.graphics.getWidth();
|
||||
int height = Gdx.graphics.getHeight();
|
||||
int xSpalt = width / 3;
|
||||
|
||||
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
|
||||
int y1 = (height - gitterD) / 2;
|
||||
int y2 = (height + gitterD) / 2;
|
||||
|
||||
drawCircularWaves(xSpalt, y1, width, height);
|
||||
drawCircularWaves(xSpalt, y2, width, height);
|
||||
shapeRenderer.end();
|
||||
|
||||
|
||||
|
||||
|
||||
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
|
||||
drawBackgroundForSinus(xSpalt, height);
|
||||
drawWallWithSlits(xSpalt, height);
|
||||
|
||||
shapeRenderer.setColor(Color.RED);
|
||||
drawIntersectionPoints(xSpalt, width, height);
|
||||
shapeRenderer.end();
|
||||
|
||||
|
||||
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
|
||||
|
||||
drawSinusWave(xSpalt, height);
|
||||
drawIncidentWave(xSpalt, height);
|
||||
shapeRenderer.end();
|
||||
}
|
||||
|
||||
private void drawSinusWave(int breite, int hoehe) {
|
||||
double phi = Math.toRadians(winkel - 90);
|
||||
double amplitude = hoehe / 12.0;
|
||||
|
||||
int lSinus;
|
||||
if (Math.abs(phi) < Math.atan(0.5 * hoehe / (double) breite)) {
|
||||
lSinus = (int) (breite / Math.cos(phi));
|
||||
} else {
|
||||
lSinus = (int) (0.5 * hoehe / Math.abs(Math.sin(phi)));
|
||||
}
|
||||
|
||||
float[] points = new float[(lSinus - 1) * 4];
|
||||
|
||||
for (int i = 0; i < lSinus - 1; i++) {
|
||||
double x0 = (i - lSinus);
|
||||
double y0 = amplitude * Math.sin(1.5 * Math.PI + 2 * Math.PI * ((i - lSinus) % lambda) / lambda);
|
||||
double x1 = (i + 1 - lSinus);
|
||||
double y1 = amplitude * Math.sin(1.5 * Math.PI + 2 * Math.PI * ((i + 1 - lSinus) % lambda) / lambda);
|
||||
|
||||
float xStart = (float) (x0 * Math.cos(phi) + y0 * Math.sin(phi)) + breite;
|
||||
float yStart = (float) (-x0 * Math.sin(phi) + y0 * Math.cos(phi)) + hoehe / 2f;
|
||||
|
||||
float xEnd = (float) (x1 * Math.cos(phi) + y1 * Math.sin(phi)) + breite;
|
||||
float yEnd = (float) (-x1 * Math.sin(phi) + y1 * Math.cos(phi)) + hoehe / 2f;
|
||||
|
||||
int idx = i * 4;
|
||||
points[idx] = xStart;
|
||||
points[idx + 1] = yStart;
|
||||
points[idx + 2] = xEnd;
|
||||
points[idx + 3] = yEnd;
|
||||
}
|
||||
|
||||
shapeRenderer.setColor(Color.RED);
|
||||
for (int i = 0; i < points.length; i += 4) {
|
||||
shapeRenderer.line(points[i], points[i + 1], points[i + 2], points[i + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void drawWallWithSlits(int xSpalt, int height) {
|
||||
int loch = 5;
|
||||
int ySpalt1 = (height - gitterD) / 2;
|
||||
int ySpalt2 = (height + gitterD) / 2;
|
||||
int balkenBreite = 5;
|
||||
|
||||
shapeRenderer.setColor(Color.BLACK);
|
||||
shapeRenderer.rect(xSpalt - 2, 0, balkenBreite, ySpalt1 - loch);
|
||||
shapeRenderer.rect(xSpalt - 2, ySpalt1 + loch, balkenBreite, gitterD - 2 * loch);
|
||||
shapeRenderer.rect(xSpalt - 2, ySpalt2 + loch, balkenBreite, height - ySpalt2 - loch);
|
||||
}
|
||||
|
||||
|
||||
private void drawBackgroundForSinus(int xSpalt, int height) {
|
||||
shapeRenderer.setColor(Color.WHITE);
|
||||
shapeRenderer.rect(0, 0, xSpalt - 5, height);
|
||||
}
|
||||
|
||||
|
||||
private void drawIncidentWave(int xSpalt, int height) {
|
||||
shapeRenderer.setColor(Color.BLACK);
|
||||
|
||||
double phi = Math.toRadians(winkel);
|
||||
double sinPhi = Math.sin(phi);
|
||||
double cosPhi = Math.cos(phi);
|
||||
|
||||
if (winkel == 90) {
|
||||
for (int i = xSpalt; i > 0; i -= lambda) {
|
||||
shapeRenderer.line(i, 0, i, height);
|
||||
}
|
||||
} else if (winkel == 0 || winkel == 180) {
|
||||
for (int i = (height / 2) % lambda; i <= height; i += lambda) {
|
||||
shapeRenderer.line(0, i, xSpalt, i);
|
||||
}
|
||||
} else {
|
||||
double dMin, dMax, d0;
|
||||
|
||||
if (winkel < 90) {
|
||||
dMin = 0.0;
|
||||
double d1 = xSpalt * sinPhi + (height / 2.0) * cosPhi;
|
||||
dMax = xSpalt * sinPhi + height * cosPhi;
|
||||
d0 = dMin + (d1 - dMin) % lambda;
|
||||
} else {
|
||||
dMin = height * cosPhi;
|
||||
double d1 = xSpalt * sinPhi + (height / 2.0) * cosPhi;
|
||||
dMax = xSpalt * sinPhi;
|
||||
d0 = dMin + (d1 - dMin) % lambda;
|
||||
}
|
||||
|
||||
for (double d = d0; d < dMax; d += lambda) {
|
||||
double schnittY_Achse = d / sinPhi;
|
||||
double schnittX_Achse = d / cosPhi;
|
||||
double schnittX_breite = (d - xSpalt * sinPhi) / cosPhi;
|
||||
double schnittY_hoehe = (d - height * cosPhi) / sinPhi;
|
||||
|
||||
int x0, y0, x1, y1;
|
||||
|
||||
if (schnittY_Achse < 0.0) {
|
||||
x0 = 0;
|
||||
y0 = (int) schnittX_Achse;
|
||||
} else if (schnittY_Achse < xSpalt) {
|
||||
x0 = (int) schnittY_Achse;
|
||||
y0 = 0;
|
||||
} else {
|
||||
x0 = xSpalt;
|
||||
y0 = (int) schnittX_breite;
|
||||
}
|
||||
|
||||
if (schnittY_hoehe < 0.0) {
|
||||
x1 = 0;
|
||||
y1 = (int) schnittX_Achse;
|
||||
} else if (schnittY_hoehe < xSpalt) {
|
||||
x1 = (int) schnittY_hoehe;
|
||||
y1 = height;
|
||||
} else {
|
||||
x1 = xSpalt;
|
||||
y1 = (int) schnittX_breite;
|
||||
}
|
||||
|
||||
shapeRenderer.line(x0, y0, x1, y1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawCircularWaves(int x, int y, int width, int height) {
|
||||
shapeRenderer.setColor(Color.BLACK);
|
||||
|
||||
double phi = Math.toRadians(winkel - 90);
|
||||
int s0;
|
||||
|
||||
if (y > height / 2) {
|
||||
s0 = (int) ((gitterD / 2.0) * Math.sin(phi)) % lambda;
|
||||
} else {
|
||||
s0 = -(int) ((gitterD / 2.0) * Math.sin(phi)) % lambda;
|
||||
}
|
||||
|
||||
if (s0 < 0) s0 += lambda;
|
||||
|
||||
for (int i = 0; i * lambda + s0 < Math.max(width, height) * 2; i++) {
|
||||
int r = i * lambda + s0;
|
||||
if (r > 0) {
|
||||
|
||||
shapeRenderer.circle(x, y, r, 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void drawIntersectionPoints(int x, int width, int height) {
|
||||
double phi = Math.toRadians(winkel - 90);
|
||||
double s0 = (gitterD / 2.0) * Math.sin(phi) % lambda;
|
||||
|
||||
int n = (int)(Math.max(width, height) * 1.5 / lambda);
|
||||
|
||||
int radius = 12;
|
||||
if (lambda <= 20) radius = 9;
|
||||
if (lambda <= 15) radius = 7;
|
||||
if (radius < 5) radius = 5;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
double r1 = i * lambda - s0;
|
||||
double r2 = j * lambda + s0;
|
||||
|
||||
if (r1 + r2 > gitterD && r1 <= r2 + gitterD && r2 <= r1 + gitterD) {
|
||||
if (gitterD != 0) {
|
||||
double y = (r1 * r1 - r2 * r2 + gitterD * gitterD) / (2.0 * gitterD);
|
||||
double xRel = Math.sqrt(Math.abs(r1 * r1 - y * y));
|
||||
|
||||
float drawX = (float) (x + xRel);
|
||||
float drawY = (float) ((height - gitterD) / 2.0 + y);
|
||||
|
||||
|
||||
if (drawY >= 0 && drawY <= height) {
|
||||
shapeRenderer.circle(drawX, drawY, radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height) {
|
||||
|
||||
viewport.update(width, height, true);
|
||||
table.setPosition(10, viewport.getWorldHeight() - 10);
|
||||
camera.setToOrtho(false, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
stage.dispose();
|
||||
shapeRenderer.dispose();
|
||||
skin.dispose();
|
||||
}
|
||||
|
||||
@Override public void pause() {}
|
||||
@Override public void resume() {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user