more consistent moving of fsm elements

This commit is contained in:
hneemann 2018-12-08 13:37:04 +01:00
parent f30b0e362f
commit 6fec5c7023
6 changed files with 146 additions and 52 deletions

View File

@ -25,6 +25,24 @@ import java.util.List;
*/
public class FSM {
/**
* The moving state of the fsm.
*/
public enum MovingState {
/**
* no elements are moving
*/
STOP,
/**
* only transitions are moving
*/
TRANSITIONS,
/**
* transitions and states are moving
*/
BOTH
}
private ArrayList<State> states;
private ArrayList<Transition> transitions;
private transient boolean modified;
@ -33,6 +51,7 @@ public class FSM {
private transient Transition initialTransition;
private transient int activeState = -1;
private transient File file;
private transient MovingState state = MovingState.STOP;
/**
* Creates a proper configured XStream instance
@ -131,6 +150,30 @@ public class FSM {
add(s);
}
/**
* Sets the moving state of this FSM
*
* @param state the state
*/
public void setMovingState(MovingState state) {
if (this.state != state) {
this.state = state;
if (state != MovingState.BOTH)
for (State s : states)
s.toRaster();
}
}
/**
* @return the moving state of this FSM
*/
public MovingState getMovingState() {
if (state == null)
state = MovingState.STOP;
return state;
}
/**
* Adds a state to the FSM
*
@ -293,19 +336,20 @@ public class FSM {
/**
* Moved the elements
*
* @param dt the time step
* @param moveStates if true also states are moved
* @param except element which is fixed
* @param dt the time step
* @param except element which is fixed
*/
public void move(int dt, boolean moveStates, Movable except) {
calculateForces();
if (moveStates)
for (State s : states)
if (s != except)
s.move(dt);
for (Transition t : transitions)
if (t != except)
t.move(dt);
public void move(int dt, Movable except) {
if (state != MovingState.STOP) {
calculateForces();
if (state == MovingState.BOTH)
for (State s : states)
if (s != except)
s.move(dt);
for (Transition t : transitions)
if (t != except)
t.move(dt);
}
}
/**
@ -353,23 +397,31 @@ public class FSM {
* @return the element or null
*/
public Movable getMovable(Vector pos) {
Movable found = null;
float dist = Float.MAX_VALUE;
for (Transition t : transitions)
if (t.matches(pos))
return t;
if (t.matches(pos)) {
float d = pos.sub(t.getPos()).len();
if (d < dist) {
dist = d;
found = t;
}
}
if (found != null)
return found;
dist = Float.MAX_VALUE;
for (State s : states)
if (s.matches(pos))
return s;
if (s.matches(pos)) {
float d = pos.sub(s.getPos()).len();
if (d < dist) {
dist = d;
found = s;
}
}
return null;
}
/**
* Move states to raster
*/
public void toRaster() {
for (State s : states)
s.toRaster();
return found;
}
/**
@ -386,7 +438,7 @@ public class FSM {
*/
public void remove(Transition transition) {
transitions.remove(transition);
wasModified();
wasModified(transition, Movable.Property.REMOVED);
resetInitInitialization();
}
@ -398,15 +450,30 @@ public class FSM {
public void remove(State state) {
states.remove(state);
transitions.removeIf(t -> t.getStartState() == state || t.getTargetState() == state);
wasModified();
wasModified(state, Movable.Property.REMOVED);
resetInitInitialization();
}
/**
* Marks the fsm as modified
*
* @param movable the element changed
* @param prop the property which has changed
*/
void wasModified() {
void wasModified(Movable movable, Movable.Property prop) {
modified = true;
if (movable instanceof State) {
State st = (State) movable;
if (prop == Movable.Property.POS && getMovingState() != MovingState.BOTH)
st.toRaster();
if ((prop == Movable.Property.POS || prop == Movable.Property.MOUSEPOS) && getMovingState() == MovingState.STOP)
for (Transition t : transitions)
if (t.getTargetState() == st || t.getStartState() == st)
t.setPos(t.getPos());
}
if (modifiedListener != null)
modifiedListener.modifiedChanged(modified);
}

View File

@ -13,6 +13,9 @@ import de.neemann.digital.draw.graphics.VectorFloat;
* @param <A> the type of the implementing class
*/
public class Movable<A extends Movable> {
enum Property {POS, REMOVED, CONDITION, NAME, NUMBER, MOUSEPOS, VALUES}
private static final float MASS = 50f;
private static final float FRICTION = 0.8f;
private static final float MAX_FORCE = 100000f;
@ -23,6 +26,7 @@ public class Movable<A extends Movable> {
private transient VectorFloat speed;
private transient VectorFloat force;
private transient FSM fsm;
private transient Property lastPosProp;
/**
* Creates a new instance
@ -33,21 +37,35 @@ public class Movable<A extends Movable> {
position = new VectorFloat(0, 0);
}
/**
* Sets the position by mouse movement
*
* @param position the position
*/
public void setPosByMouse(VectorFloat position) {
setPos(position, Property.MOUSEPOS);
}
/**
* Sets the position
*
* @param position the position
*/
public void setPos(VectorFloat position) {
if (!this.position.equals(position)) {
setPos(position, Property.POS);
}
private void setPos(VectorFloat position, Property prop) {
if (!this.position.equals(position) || lastPosProp != prop) {
this.position = position;
wasModified();
lastPosProp = prop;
wasModified(prop);
}
}
void wasModified() {
void wasModified(Property prop) {
if (fsm != null)
fsm.wasModified();
fsm.wasModified(this, prop);
}
/**
@ -167,7 +185,7 @@ public class Movable<A extends Movable> {
public A setValues(String values) {
if (!this.values.equals(values)) {
this.values = values;
wasModified();
wasModified(Property.VALUES);
}
return (A) this;
}

View File

@ -52,7 +52,7 @@ public class State extends Movable<State> {
public void setName(String name) {
if (!this.name.equals(name)) {
this.name = name;
wasModified();
wasModified(Property.NAME);
}
}
@ -158,7 +158,7 @@ public class State extends Movable<State> {
public State setNumber(int number) {
if (this.number != number) {
this.number = number;
wasModified();
wasModified(Property.NUMBER);
if (getFsm() != null)
getFsm().resetInitInitialization();
}

View File

@ -92,8 +92,18 @@ public class Transition extends Movable<Transition> {
return getFsm() != null && getFsm().isInitial(this);
}
@Override
public void setPosByMouse(VectorFloat position) {
super.setPosByMouse(posConstrain(position));
}
@Override
public void setPos(VectorFloat position) {
super.setPos(posConstrain(position));
}
private VectorFloat posConstrain(VectorFloat position) {
if (fromState != toState) {
VectorFloat dist = toState.getPos().sub(fromState.getPos());
if (dist.getXFloat() != 0 || dist.getYFloat() != 0) {
@ -104,11 +114,10 @@ public class Transition extends Movable<Transition> {
VectorFloat p = position.sub(start);
VectorFloat n = dist.getOrthogonal();
float l = p.mul(n);
super.setPos(start.add(end).div(2).add(n.mul(l)));
return;
return start.add(end).div(2).add(n.mul(l));
}
}
super.setPos(position);
return position;
}
/**
@ -198,7 +207,7 @@ public class Transition extends Movable<Transition> {
public void setCondition(String condition) {
if (!this.condition.equals(condition)) {
this.condition = condition;
wasModified();
wasModified(Property.CONDITION);
conditionExpression = null;
if (getFsm() != null)
getFsm().resetInitInitialization();

View File

@ -91,8 +91,8 @@ public class FSMComponent extends JComponent {
@Override
public void mouseReleased(MouseEvent mouseEvent) {
if (elementMoved instanceof State) {
((State) elementMoved).toRaster();
if (elementMoved != null) {
elementMoved.setPos(getPosVector(mouseEvent).sub(delta).toFloat());
repaint();
}
elementMoved = null;
@ -140,7 +140,7 @@ public class FSMComponent extends JComponent {
repaint();
}
if (elementMoved != null) {
elementMoved.setPos(getPosVector(e).sub(delta).toFloat());
elementMoved.setPosByMouse(getPosVector(e).sub(delta).toFloat());
repaint();
}
if (newTransitionFromState != null)

View File

@ -54,7 +54,6 @@ public class FSMFrame extends JFrame implements ClosingWindowListener.ConfirmSav
private final Timer timer;
private final JComboBox<String> moveControl;
private FSM fsm;
private boolean moveStates = false;
private ToolTipAction save;
private File filename;
private File baseFilename;
@ -78,9 +77,13 @@ public class FSMFrame extends JFrame implements ClosingWindowListener.ConfirmSav
timer = new Timer(100, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
for (int i = 0; i < 100; i++)
fsm.move(10, moveStates, fsmComponent.getElementMoved());
repaint();
if (fsm.getMovingState() == FSM.MovingState.STOP)
timer.stop();
else {
for (int i = 0; i < 100; i++)
fsm.move(10, fsmComponent.getElementMoved());
repaint();
}
}
});
@ -111,18 +114,15 @@ public class FSMFrame extends JFrame implements ClosingWindowListener.ConfirmSav
public void actionPerformed(ActionEvent actionEvent) {
switch (moveControl.getSelectedIndex()) {
case 0:
timer.stop();
fsm.toRaster();
fsm.setMovingState(FSM.MovingState.STOP);
fsmComponent.repaint();
break;
case 1:
if (moveStates)
fsm.toRaster();
moveStates = false;
fsm.setMovingState(FSM.MovingState.TRANSITIONS);
timer.start();
break;
case 2:
moveStates = true;
fsm.setMovingState(FSM.MovingState.BOTH);
timer.start();
break;
}