better init state handling

This commit is contained in:
hneemann 2018-11-24 21:23:53 +01:00
parent 37ddaf01f6
commit b8ab4a526e
4 changed files with 63 additions and 35 deletions

View File

@ -26,9 +26,10 @@ public class FSM {
private ArrayList<State> states;
private ArrayList<Transition> transitions;
private transient boolean initChecked;
private transient boolean modified;
private transient ModifiedListener modifiedListener;
private transient boolean isInitialChecked;
private transient Transition initialTransition;
/**
* Creates a proper configured XStream instance
@ -134,6 +135,7 @@ public class FSM {
state.setNumber(states.size());
state.setFSM(this);
states.add(state);
resetInitInitialization();
return this;
}
@ -146,6 +148,7 @@ public class FSM {
public FSM add(Transition transition) {
transitions.add(transition);
transition.setFSM(this);
resetInitInitialization();
return this;
}
@ -230,10 +233,6 @@ public class FSM {
* @param gr the Graphic instance to draw to
*/
public void drawTo(Graphic gr) {
if (!initChecked) {
checkInitState();
initChecked = true;
}
for (State s : states)
s.drawTo(gr);
for (Transition t : transitions)
@ -241,6 +240,9 @@ public class FSM {
}
private void checkInitState() {
initialTransition = null;
isInitialChecked = true;
int count = 0;
Transition found = null;
for (Transition t : transitions) {
@ -248,17 +250,33 @@ public class FSM {
count++;
found = t;
}
if (t.getTargetState().getNumber() == 0)
return;
}
try {
if (count == 1 && !found.hasCondition()) {
found.getStartState().setInitial();
found.setInitial();
}
if (count == 1 && !found.hasCondition())
initialTransition = found;
} catch (FiniteStateMachineException e) {
// ignore
}
}
void resetInitInitialization() {
isInitialChecked = false;
}
boolean isInitial(State state) {
if (!isInitialChecked)
checkInitState();
return initialTransition != null && state.getNumber() == 0;
}
boolean isInitial(Transition transition) {
if (!isInitialChecked)
checkInitState();
return transition == initialTransition;
}
/**
* Moved the elements
*
@ -286,8 +304,8 @@ public class FSM {
double delta = 2 * Math.PI / states.size();
double rad = 0;
for (State s : states)
if (s.getRadius() > rad)
rad = s.getRadius();
if (s.getVisualRadius() > rad)
rad = s.getVisualRadius();
rad *= 4;
double phi = 0;
@ -354,6 +372,7 @@ public class FSM {
public void remove(Transition transition) {
transitions.remove(transition);
wasModified();
resetInitInitialization();
}
/**
@ -365,6 +384,7 @@ public class FSM {
states.remove(state);
transitions.removeIf(t -> t.getStartState() == state || t.getTargetState() == state);
wasModified();
resetInitInitialization();
}
/**

View File

@ -18,6 +18,7 @@ public class State extends Movable {
private static final int RAD = 70;
private static final float REACH = 2000;
private static final int INIT_RADIUS = 20;
private int number = -1;
private String name;
@ -25,7 +26,6 @@ public class State extends Movable {
private String values = "";
private transient TreeMap<String, Integer> valueMap;
private transient boolean isInitial;
/**
* Creates a new state
@ -119,8 +119,8 @@ public class State extends Movable {
* @param gr the Graphic instance to draw to
*/
public void drawTo(Graphic gr) {
if (isInitial) {
VectorInterface rad = new Vector(radius, radius);
if (isInitialState()) {
VectorInterface rad = new Vector(INIT_RADIUS, INIT_RADIUS);
gr.drawCircle(getPos().sub(rad), getPos().add(rad), Style.FILLED);
} else {
VectorInterface rad = new Vector(radius, radius);
@ -144,6 +144,20 @@ public class State extends Movable {
}
}
private boolean isInitialState() {
return getFsm() != null && getFsm().isInitial(this);
}
/**
* @return the radius of the state
*/
float getVisualRadius() {
if (isInitialState())
return INIT_RADIUS;
else
return radius;
}
/**
* @return the radius of the state
*/
@ -161,6 +175,8 @@ public class State extends Movable {
if (this.number != number) {
this.number = number;
wasModified();
if (getFsm() != null)
getFsm().resetInitInitialization();
}
return this;
}
@ -202,11 +218,4 @@ public class State extends Movable {
return this;
}
/**
* Makes this state the initial state
*/
public void setInitial() {
isInitial = true;
radius = 20;
}
}

View File

@ -27,7 +27,6 @@ public class Transition extends Movable {
private String condition = "";
private String values = "";
private transient Expression conditionExpression;
private transient boolean isInitial;
private transient TreeMap<String, Integer> valuesMap;
@ -53,9 +52,7 @@ public class Transition extends Movable {
* @param transitions the transitions
*/
public void calcForce(List<State> states, List<Transition> transitions) {
float preferredDist = 20;
if (!isInitial)
preferredDist = Math.max(fromState.getRadius(), toState.getRadius()) * 5;
float preferredDist = Math.max(fromState.getVisualRadius(), toState.getVisualRadius()) * 5;
calcForce(preferredDist, states, transitions);
}
@ -81,7 +78,7 @@ public class Transition extends Movable {
VectorFloat center = fromState.getPos().add(toState.getPos()).mul(0.5f);
addAttractiveTo(center, 1);
if (!isInitial) {
if (!isInitialTransition()) {
for (State s : states)
addRepulsive(s.getPos(), 2000);
@ -91,6 +88,10 @@ public class Transition extends Movable {
}
}
private boolean isInitialTransition() {
return getFsm() != null && getFsm().isInitial(this);
}
@Override
public void setPos(VectorFloat position) {
if (fromState != toState) {
@ -120,9 +121,9 @@ public class Transition extends Movable {
anchorTo = anchorTo.sub(dif);
}
VectorFloat difFrom = anchorFrom.sub(fromState.getPos()).norm().mul(fromState.getRadius() + Style.MAXLINETHICK);
VectorFloat difTo = anchorTo.sub(toState.getPos()).norm().mul(toState.getRadius() + Style.MAXLINETHICK + 2);
VectorFloat difToTip = anchorTo.sub(toState.getPos()).norm().mul(toState.getRadius() + Style.MAXLINETHICK);
VectorFloat difFrom = anchorFrom.sub(fromState.getPos()).norm().mul(fromState.getVisualRadius() + Style.MAXLINETHICK);
VectorFloat difTo = anchorTo.sub(toState.getPos()).norm().mul(toState.getVisualRadius() + Style.MAXLINETHICK + 2);
VectorFloat difToTip = anchorTo.sub(toState.getPos()).norm().mul(toState.getVisualRadius() + Style.MAXLINETHICK);
final VectorFloat start = fromState.getPos().add(difFrom);
final VectorFloat end = toState.getPos().add(difTo);
@ -167,6 +168,8 @@ public class Transition extends Movable {
this.condition = condition;
wasModified();
conditionExpression = null;
if (getFsm()!=null)
getFsm().resetInitInitialization();
}
}
@ -268,10 +271,4 @@ public class Transition extends Movable {
return fromState + " --[" + condition + "]-> " + toState;
}
/**
* Mark this transition as initial transition
*/
public void setInitial() {
isInitial = true;
}
}

View File

@ -263,6 +263,7 @@ public class FSMFrame extends JFrame implements ClosingWindowListener.ConfirmSav
moveControl.setSelectedIndex(0);
setFSM(FSM.loadFSM(file));
setFilename(file);
lastModified=fsm.isModified();
} catch (IOException e) {
new ErrorMessage(Lang.get("msg_fsm_errorLoadingFile")).addCause(e).show(this);
}
@ -273,6 +274,7 @@ public class FSMFrame extends JFrame implements ClosingWindowListener.ConfirmSav
fsm.save(file);
setFilename(file);
save.setEnabled(false);
lastModified=fsm.isModified();
} catch (IOException e) {
new ErrorMessage(Lang.get("msg_fsm_errorStoringFile")).addCause(e).show(this);
}