protected void update() { Log.debug("Updater.update: in update"); List<Long> perceiverOids = null; lock.lock(); try { perceiverOids = new ArrayList<Long>(perceiverDataMap.keySet()); } finally { lock.unlock(); } // We loop over the copied perceiverOids causing // interpolation to happen, and capturing the location in // the PerceiverData, so we can later do comparisons // cheaply. Note that underlying map can change while // we're doing so, so we don't raise errors if it happens. for (long perceiverOid : perceiverOids) { PerceiverData perceiverData = perceiverDataMap.get(perceiverOid); if (perceiverData != null) { perceiverData.previousLoc = perceiverData.lastLoc; // long lastInterp = perceiverData.wnode.getLastInterp(); perceiverData.lastLoc = perceiverData.wnode.getLoc(); // if (Log.loggingDebug) // Log.debug("Updater.update: perceiverOid " + perceiverOid + ", // previousLoc " + perceiverData.previousLoc + // ", lastLoc " + perceiverData.lastLoc + ", time since interp // " + (System.currentTimeMillis() - lastInterp)); } } // Now actually do the double loop to check if inRange has // changed for (long perceiverOid : perceiverOids) { PerceiverData perceiverData = perceiverDataMap.get(perceiverOid); if (perceiverData == null) continue; // If the perceiver hasn't moved much, no need to // iterate over it's perceived entities if (perceiverData.previousLoc != null && Point.distanceToSquared(perceiverData.previousLoc, perceiverData.lastLoc) < 100f) continue; ArrayList<Long> perceivedOids = new ArrayList<Long>(perceiverData.perceivedOids); for (long perceivedOid : perceivedOids) { PerceiverData perceivedData = perceiverDataMap.get(perceivedOid); if (perceivedData == null) continue; // Invoke the testProximity method but tell it not // to interpolate, but instead get its location // from the PerceptionData.lastLoc members testProximity(perceiverData, perceivedData, false, false); } } }
/** * Test if the perceived object has come in or out of range of the perceiver object; if so, we * change the inRangeOids set for the perceiver, and notify the perceiver. */ protected void testProximity( PerceiverData perceiverData, PerceiverData perceivedData, boolean interpolatePerceiver, boolean interpolatePerceived) { Point perceiverLoc = interpolatePerceiver ? perceiverData.wnode.getLoc() : perceiverData.lastLoc; Point perceivedLoc = interpolatePerceived ? perceivedData.wnode.getLoc() : perceivedData.lastLoc; float distance = Point.distanceTo(perceiverLoc, perceivedLoc); float reactionRadius = perceiverData.reactionRadius; long perceiverInstance = perceiverData.wnode.getInstanceOid(); long perceivedInstance = perceivedData.wnode.getInstanceOid(); boolean sameInstance = perceiverInstance == perceivedInstance; boolean inRadius = sameInstance && (distance < reactionRadius); boolean wasInRadius = perceiverData.inRangeOids.contains(perceivedData.perceiverOid); // if (Log.loggingDebug) // Log.debug("ProximityTracker.testProximity: perceiver " + // perceiverData.perceiverOid + ", perceiverLoc = " + perceiverLoc + // ", perceived " + perceivedData.perceiverOid + ", perceivedLoc = " + // perceivedLoc + // ", distance " + distance + ", reactionRadius " + reactionRadius + ", // perceiverInstance " + perceiverInstance + // ", perceivedInstance " + perceivedInstance + ", inRadius " + inRadius + ", // wasInRadius " + wasInRadius); if (inRadius == wasInRadius) return; if (sameInstance && hystericalMargin != 0f) { if (wasInRadius) inRadius = distance < (reactionRadius + hystericalMargin); else inRadius = distance < (reactionRadius - hystericalMargin); // If they are the same after hysteresis was applied, skip. if (inRadius == wasInRadius) return; } if (inRadius) { perceiverData.inRangeOids.add(perceivedData.perceiverOid); perceivedData.inRangeOids.add(perceiverData.perceiverOid); } else { perceiverData.inRangeOids.remove(perceivedData.perceiverOid); perceivedData.inRangeOids.remove(perceiverData.perceiverOid); } performNotification( perceiverData.perceiverOid, perceivedData.perceiverOid, inRadius, wasInRadius); }