super.fire();
while (input.hasToken(0)) {
RecordToken recordToken = (RecordToken) input.get(0);
ArrayToken locationArray = (ArrayToken) recordToken.get("location");
if (locationArray.length() < 2) {
throw new IllegalActionException(this,
"Input is malformed: location field does not "
+ "have two entries.");
}
double locationX = ((DoubleToken) locationArray.getElement(0))
.doubleValue();
double locationY = ((DoubleToken) locationArray.getElement(1))
.doubleValue();
double time = ((DoubleToken) recordToken.get("time")).doubleValue();
// First check whether the location matches one already in the
// buffer. At the same time, identify the entry with the
// oldest time and the newest time.
boolean foundMatch = false;
int oldestTimeIndex = 0;
double oldestTime = Double.POSITIVE_INFINITY;
double newestTime = Double.NEGATIVE_INFINITY;
for (int i = 0; i < 3; i++) {
if ((_locationsX[i] == locationX)
&& (_locationsY[i] == locationY)) {
_times[i] = time;
foundMatch = true;
}
if (_times[i] < oldestTime) {
oldestTime = _times[i];
oldestTimeIndex = i;
}
if (_times[i] > newestTime) {
newestTime = _times[i];
}
}
if (!foundMatch) {
if (_debugging) {
_debug("Did not find match");
}
_locationsX[oldestTimeIndex] = locationX;
_locationsY[oldestTimeIndex] = locationY;
_times[oldestTimeIndex] = time;
// Have to recalculate the oldest time now
// since it has changed.
oldestTime = Double.POSITIVE_INFINITY;
for (int i = 0; i < 3; i++) {
if (_times[i] < oldestTime) {
oldestTime = _times[i];
}
}
}
// Next check whether we have three observations within
// the specified time window. Since the time entries are
// all initialized to negative infinity, the time span
// will be infinity if we have not seen three observations
// from three distinct locations.
double timeSpan = newestTime - oldestTime;
double timeWindowValue = ((DoubleToken) timeWindow.getToken())
.doubleValue();
if (timeSpan > timeWindowValue) {
// We do not have enough data.
if (_debugging) {
_debug("We do not have enough data: " + timeSpan + " > " + timeWindowValue);
}
return;
}
// Get signal speed, from the signalPropagationSpeed parameter.
double speed = ((DoubleToken) (signalPropagationSpeed.getToken()))
.doubleValue();
// FIXME: Pass in the arrays for scalability.
// FIXME: Replace naked 3 everywhere.
double[] result = _locate(_locationsX[0], _locationsY[0],
_times[0], _locationsX[1], _locationsY[1], _times[1],
_locationsX[2], _locationsY[2], _times[2], speed);
if (Double.isInfinite(result[2]) || Double.isNaN(result[2])) {
// Result is not valid (inconsistent data).
if (_debugging) {
_debug("Result is not valid: " + result[2]);
}
return;
}
Token[] resultArray = new Token[2];
resultArray[0] = new DoubleToken(result[0]);
resultArray[1] = new DoubleToken(result[1]);
output.broadcast(new ArrayToken(resultArray));
}
}