Properly fire changes after wind model change
This commit is contained in:
parent
b9d2ebd16b
commit
4a3b9efe76
@ -1,15 +1,22 @@
|
|||||||
package info.openrocket.core.models.wind;
|
package info.openrocket.core.models.wind;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.EventListener;
|
||||||
|
import java.util.EventObject;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import info.openrocket.core.util.ChangeSource;
|
||||||
import info.openrocket.core.util.Coordinate;
|
import info.openrocket.core.util.Coordinate;
|
||||||
import info.openrocket.core.util.ModID;
|
import info.openrocket.core.util.ModID;
|
||||||
|
import info.openrocket.core.util.StateChangeListener;
|
||||||
|
|
||||||
public class MultiLevelPinkNoiseWindModel implements WindModel {
|
public class MultiLevelPinkNoiseWindModel implements WindModel {
|
||||||
private List<LevelWindModel> levels;
|
private List<LevelWindModel> levels;
|
||||||
|
|
||||||
|
private final List<StateChangeListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
public MultiLevelPinkNoiseWindModel() {
|
public MultiLevelPinkNoiseWindModel() {
|
||||||
this.levels = new ArrayList<>();
|
this.levels = new ArrayList<>();
|
||||||
}
|
}
|
||||||
@ -21,23 +28,28 @@ public class MultiLevelPinkNoiseWindModel implements WindModel {
|
|||||||
pinkNoiseModel.setDirection(direction);
|
pinkNoiseModel.setDirection(direction);
|
||||||
|
|
||||||
LevelWindModel newLevel = new LevelWindModel(altitude, pinkNoiseModel);
|
LevelWindModel newLevel = new LevelWindModel(altitude, pinkNoiseModel);
|
||||||
|
newLevel.addChangeListener(e -> fireChangeEvent());
|
||||||
int index = Collections.binarySearch(levels, newLevel, Comparator.comparingDouble(l -> l.altitude));
|
int index = Collections.binarySearch(levels, newLevel, Comparator.comparingDouble(l -> l.altitude));
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
throw new IllegalArgumentException("Wind level already exists for altitude: " + altitude);
|
throw new IllegalArgumentException("Wind level already exists for altitude: " + altitude);
|
||||||
}
|
}
|
||||||
levels.add(-index - 1, newLevel);
|
levels.add(-index - 1, newLevel);
|
||||||
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeWindLevel(double altitude) {
|
public void removeWindLevel(double altitude) {
|
||||||
levels.removeIf(level -> level.altitude == altitude);
|
levels.removeIf(level -> level.altitude == altitude);
|
||||||
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeWindLevelIdx(int index) {
|
public void removeWindLevelIdx(int index) {
|
||||||
levels.remove(index);
|
levels.remove(index);
|
||||||
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearLevels() {
|
public void clearLevels() {
|
||||||
levels.clear();
|
levels.clear();
|
||||||
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LevelWindModel> getLevels() {
|
public List<LevelWindModel> getLevels() {
|
||||||
@ -127,10 +139,12 @@ public class MultiLevelPinkNoiseWindModel implements WindModel {
|
|||||||
return levels.hashCode();
|
return levels.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LevelWindModel implements Cloneable {
|
public static class LevelWindModel implements Cloneable, ChangeSource {
|
||||||
protected double altitude;
|
protected double altitude;
|
||||||
protected PinkNoiseWindModel model;
|
protected PinkNoiseWindModel model;
|
||||||
|
|
||||||
|
private final List<StateChangeListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
LevelWindModel(double altitude, PinkNoiseWindModel model) {
|
LevelWindModel(double altitude, PinkNoiseWindModel model) {
|
||||||
this.altitude = altitude;
|
this.altitude = altitude;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
@ -142,6 +156,7 @@ public class MultiLevelPinkNoiseWindModel implements WindModel {
|
|||||||
|
|
||||||
public void setAltitude(double altitude) {
|
public void setAltitude(double altitude) {
|
||||||
this.altitude = altitude;
|
this.altitude = altitude;
|
||||||
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getSpeed() {
|
public double getSpeed() {
|
||||||
@ -194,5 +209,49 @@ public class MultiLevelPinkNoiseWindModel implements WindModel {
|
|||||||
LevelWindModel that = (LevelWindModel) obj;
|
LevelWindModel that = (LevelWindModel) obj;
|
||||||
return Double.compare(that.altitude, altitude) == 0 && model.equals(that.model);
|
return Double.compare(that.altitude, altitude) == 0 && model.equals(that.model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addChangeListener(StateChangeListener listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
model.addChangeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeChangeListener(StateChangeListener listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
model.removeChangeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fireChangeEvent() {
|
||||||
|
EventObject event = new EventObject(this);
|
||||||
|
// Copy the list before iterating to prevent concurrent modification exceptions.
|
||||||
|
EventListener[] list = listeners.toArray(new EventListener[0]);
|
||||||
|
for (EventListener l : list) {
|
||||||
|
if (l instanceof StateChangeListener) {
|
||||||
|
((StateChangeListener) l).stateChanged(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addChangeListener(StateChangeListener listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeChangeListener(StateChangeListener listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fireChangeEvent() {
|
||||||
|
EventObject event = new EventObject(this);
|
||||||
|
// Copy the list before iterating to prevent concurrent modification exceptions.
|
||||||
|
EventListener[] list = listeners.toArray(new EventListener[0]);
|
||||||
|
for (EventListener l : list) {
|
||||||
|
if (l instanceof StateChangeListener) {
|
||||||
|
((StateChangeListener) l).stateChanged(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +1,16 @@
|
|||||||
package info.openrocket.core.models.wind;
|
package info.openrocket.core.models.wind;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.EventListener;
|
||||||
|
import java.util.EventObject;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import info.openrocket.core.util.Coordinate;
|
import info.openrocket.core.util.Coordinate;
|
||||||
import info.openrocket.core.util.MathUtil;
|
import info.openrocket.core.util.MathUtil;
|
||||||
import info.openrocket.core.util.ModID;
|
import info.openrocket.core.util.ModID;
|
||||||
import info.openrocket.core.util.PinkNoise;
|
import info.openrocket.core.util.PinkNoise;
|
||||||
|
import info.openrocket.core.util.StateChangeListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wind simulator that generates wind speed as pink noise from a specified
|
* A wind simulator that generates wind speed as pink noise from a specified
|
||||||
@ -46,6 +51,8 @@ public class PinkNoiseWindModel implements WindModel {
|
|||||||
private double time1;
|
private double time1;
|
||||||
private double value1, value2;
|
private double value1, value2;
|
||||||
|
|
||||||
|
private final List<StateChangeListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new wind simulation with a specific seed value.
|
* Construct a new wind simulation with a specific seed value.
|
||||||
*
|
*
|
||||||
@ -222,4 +229,24 @@ public class PinkNoiseWindModel implements WindModel {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addChangeListener(StateChangeListener listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeChangeListener(StateChangeListener listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fireChangeEvent() {
|
||||||
|
EventObject event = new EventObject(this);
|
||||||
|
// Copy the list before iterating to prevent concurrent modification exceptions.
|
||||||
|
EventListener[] list = listeners.toArray(new EventListener[0]);
|
||||||
|
for (EventListener l : list) {
|
||||||
|
if (l instanceof StateChangeListener) {
|
||||||
|
((StateChangeListener) l).stateChanged(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,38 +3,9 @@ package info.openrocket.core.models.wind;
|
|||||||
import info.openrocket.core.util.ChangeSource;
|
import info.openrocket.core.util.ChangeSource;
|
||||||
import info.openrocket.core.util.Coordinate;
|
import info.openrocket.core.util.Coordinate;
|
||||||
import info.openrocket.core.util.Monitorable;
|
import info.openrocket.core.util.Monitorable;
|
||||||
import info.openrocket.core.util.StateChangeListener;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.EventListener;
|
|
||||||
import java.util.EventObject;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface WindModel extends Monitorable, Cloneable, ChangeSource {
|
public interface WindModel extends Monitorable, Cloneable, ChangeSource {
|
||||||
List<StateChangeListener> listeners = new ArrayList<>();
|
|
||||||
|
|
||||||
Coordinate getWindVelocity(double time, double altitude);
|
Coordinate getWindVelocity(double time, double altitude);
|
||||||
|
|
||||||
WindModel clone();
|
WindModel clone();
|
||||||
|
|
||||||
@Override
|
|
||||||
default void addChangeListener(StateChangeListener listener) {
|
|
||||||
listeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default void removeChangeListener(StateChangeListener listener) {
|
|
||||||
listeners.remove(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void fireChangeEvent() {
|
|
||||||
EventObject event = new EventObject(this);
|
|
||||||
// Copy the list before iterating to prevent concurrent modification exceptions.
|
|
||||||
EventListener[] list = listeners.toArray(new EventListener[0]);
|
|
||||||
for (EventListener l : list) {
|
|
||||||
if (l instanceof StateChangeListener) {
|
|
||||||
((StateChangeListener) l).stateChanged(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,9 @@ public class SimulationOptions implements ChangeSource, Cloneable, SimulationOpt
|
|||||||
|
|
||||||
public SimulationOptions() {
|
public SimulationOptions() {
|
||||||
averageWindModel = new PinkNoiseWindModel(randomSeed);
|
averageWindModel = new PinkNoiseWindModel(randomSeed);
|
||||||
|
averageWindModel.addChangeListener(e -> fireChangeEvent());
|
||||||
multiLevelPinkNoiseWindModel = new MultiLevelPinkNoiseWindModel();
|
multiLevelPinkNoiseWindModel = new MultiLevelPinkNoiseWindModel();
|
||||||
|
multiLevelPinkNoiseWindModel.addChangeListener(e -> fireChangeEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getLaunchRodLength() {
|
public double getLaunchRodLength() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user