package affectors; import main.Node; import main.Globals; /** An artificial Affector which brings a Node from its initial value to a second value starting at a specified time and taking a specified amount of time to do the change. Then it holds it at the second value for another specified period of time. Finally, it drops it to a final value over yet another specified period of time. You might use this for a transient pre-pattern, for instance. Note that by setting some of the times to 0, you can simplify the pattern produced.

AN ADDITIONAL COMPLICATION: In order that this affector can be used in a spatially patterned way, the affector pays attention to the initial values in each cell. If the initial value is 0, then the affector always returns 0. If the initial value is 0.00001 or less, the value that this affector is trying to reach is multiplied by / 0.00001. If the init value is > 0.00001, there is no special behavior.

Formula
dnodex/dt = 0 | before first_time
dnodex/dt = (second_value - initial_value) / (second_time - first_time) | between first and second times
dnodex/dt = 0 | between second and third times
dnodex/dt = (third_value - second_value) / (fourth_time - third_time) | between third and fourth times
dnodex/dt = 0 | after fourth_time

Parameters
Target [nodex] The Node which this Affector is acting on
First time [first_t] See formula above
Second time [second_t] See formula above
Third time [third_t] See formula above
Fourth time [fourth_t] See formula above
Second value [second_v] See formula above
Third value [third_v] See formula above

Usage
&nodex

&DefinedValuesAff nodex first_t second_t third_t fourth_t second_v third_v
&endnodex */ public class DefinedValuesAff extends Affector { int firstTime, secondTime, thirdTime, fourthTime, secondValue, thirdValue; float initValue, scaleValue; static final String desc = "Rises and/or falls to defined values at given speeds"; static final String [] nodeDescriptions = {"Target"}; static final String [] paramDescriptions = {"First time", "Second time", "Third time", "Fourth time", "Second value", "Third value"}; static final int [] whichSides = { -1 }; public DefinedValuesAff() {} protected void setLabelsAndTypes() { setDescriptions(this.desc, nodeDescriptions, paramDescriptions); setSided(true, whichSides); setContainsTarget(true); this.Type[GUI_CAPABLE] = 1; this.Type[CERTIFICATION] = Affector.RETURNS_DERIV; this.Type[MATHTYPE] = Affector.CC; this.Type[TERMTYPE] = Affector.DEGRADATION; } public void setParameterNumbers(int [] param_nums) { firstTime = param_nums[0]; secondTime = param_nums[1]; thirdTime = param_nums[2]; fourthTime = param_nums[3]; secondValue = param_nums[4]; thirdValue = param_nums[5]; } public float getValue(Node which_node) { float val; // Get the initial value - not totally clean, but should work if(Globals.time == 0) { initValue = Nodes[0].getValue(side); if(initValue <= 0.00001) scaleValue = initValue / 0.00001f; else scaleValue = 1f; } if(initValue == 0) val = 0f; else if(Globals.time < params[firstTime]) val = 0.0f; else if(Globals.time >= params[firstTime] && Globals.time < params[secondTime]) val = Globals.characteristicTime * scaleValue * (params[secondValue] - initValue) / (params[secondTime] - params[firstTime]); else if(Globals.time >= params[secondTime] && Globals.time < params[thirdTime]) val = 0f; else if(Globals.time >= params[thirdTime] && Globals.time < params[fourthTime]) val = Globals.characteristicTime * scaleValue * (params[thirdValue] - params[secondValue]) / (params[fourthTime] - params[thirdTime]); else val = Globals.characteristicTime * (params[thirdValue] - Nodes[0].getIntegrationValue(side)); return val; } }