diff --git a/tools/cooja/apps/arm/build.xml b/tools/cooja/apps/arm/build.xml deleted file mode 100644 index 67c9f1228..000000000 --- a/tools/cooja/apps/arm/build.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/cooja/apps/arm/cooja.config b/tools/cooja/apps/arm/cooja.config deleted file mode 100644 index e5697df94..000000000 --- a/tools/cooja/apps/arm/cooja.config +++ /dev/null @@ -1,2 +0,0 @@ -se.sics.cooja.GUI.RADIOMEDIUMS = + se.sics.arm.AdvancedRadioMedium -se.sics.cooja.GUI.JARFILES = + arm.jar jfreechart-1.0.1.jar jcommon-1.0.0.jar diff --git a/tools/cooja/apps/arm/images/antenna.png b/tools/cooja/apps/arm/images/antenna.png deleted file mode 100644 index f3d82e08e..000000000 Binary files a/tools/cooja/apps/arm/images/antenna.png and /dev/null differ diff --git a/tools/cooja/apps/arm/java/se/sics/arm/AdvancedRadioMedium.java b/tools/cooja/apps/arm/java/se/sics/arm/AdvancedRadioMedium.java deleted file mode 100644 index b3d963b8e..000000000 --- a/tools/cooja/apps/arm/java/se/sics/arm/AdvancedRadioMedium.java +++ /dev/null @@ -1,658 +0,0 @@ -package se.sics.arm; - -import java.util.*; -import org.apache.log4j.Logger; -import org.jdom.Element; - -import se.sics.cooja.*; -import se.sics.cooja.interfaces.*; - -/** - * This is the main class of the COOJA Advanced Radio Medium (ARM) package. - * - * ARM is meant to be a replacement for the simpler radio mediums available in - * COOJA. It is packet based and uses a 2D ray-tracing approach to approximate - * signal strength attenuations between simulated radios. Currently the - * ray-tracing only supports reflections and refractions through homogeneous - * obstacles. - * - * ARM provides a number of plugins for example a plugin for visualizing radio - * environments, and a plugin for configuring the radio medium. - * - * When a radio transmits data the area of interference around it will be - * occupied for a time depending on the length of the packet sent. If the entire - * transmission is completed without any interference the packet will be - * delivered, otherwise nothing will be delivered. - * - * Future work includes adding diffractions and scattering support. - * - * @author Fredrik Osterlind - */ -@ClassDescription("Advanced Radio Medium (ARM)") -public class AdvancedRadioMedium extends RadioMedium { - private static Logger logger = Logger.getLogger(AdvancedRadioMedium.class); - - private ChannelModel currentChannelModel = null; - private Observer simulationObserver = null; - private Simulation mySimulation = null; - - // Registered members of radio medium - private Vector registeredMembers = new Vector(); - - private Vector allTransmissions = new Vector(); - private Vector allTransfers = new Vector(); - private Vector allInterferences = new Vector(); - - - /** - * Notifies observers when this radio medium is starting or has finished a packet delivery. - */ - private TransmissionsObservable radioActivityObservable = new TransmissionsObservable(); - - /** - * Notifies observers when this radio medium has changed settings. - */ - private SettingsObservable settingsObservable = new SettingsObservable(); - - /** - * Listens to all registered radios, and fetches any new incoming radio packets. - */ - private Observer radioObserver = new Observer() { - public void update(Observable radio, Object obj) { - Radio sendingRadio = (Radio) radio; - if (sendingRadio.getLastEvent() != Radio.RadioEvent.TRANSMISSION_STARTED) - return; - - // Locate corresponding member - ARMMember sendingMember = null; - for (ARMMember member: registeredMembers) { - if (member.radio == radio) { - sendingMember = member; - break; - } - } - if (sendingMember == null) { - logger.fatal("ARM: Could not locate radio member - is radio registered? " + radio); - return; - } - - // Check that member is not receiving data - if (sendingMember.isListeningOnTransmission()) { - logger.fatal("ARM: Radio is trying to send data but is currently receiving! This must be fixed in Contiki!"); - return; - } - - // Check that member is not already sending data - for (RadioTransmission transmission: allTransmissions) { - if (transmission.source == sendingMember) { - logger.fatal("ARM: Radio is trying to send data but is already sending! This must be fixed in Contiki!"); - return; - } - } - - int transmissionEndTime = sendingRadio.getTransmissionEndTime(); - - // Create transmission - byte[] packetToSend = sendingRadio.getLastPacketTransmitted(); - RadioTransmission transmission = new RadioTransmission(sendingMember, transmissionEndTime, packetToSend); - allTransmissions.add(transmission); - radioActivityObservable.notifyRadioActivityChanged(); // Need to notify observers - - double sendingX = sendingMember.position.getXCoordinate(); - double sendingY = sendingMember.position.getYCoordinate(); - Random random = new Random(); - - // Calculate how the other radios will be affected by this packet - for (ARMMember member: registeredMembers) { - // Ignore this sending radio - if (member != sendingMember) { - double receivingX = member.position.getXCoordinate(); - double receivingY = member.position.getYCoordinate(); - - double[] probData = currentChannelModel.getProbability(sendingX, sendingY, receivingX, receivingY, -Double.MAX_VALUE); - - //logger.info("Probability of reception is " + probData[0]); - //logger.info("Signal strength at destination is " + probData[1]); - if (random.nextFloat() < probData[0]) { - // Connection successful (if not interfered later) - //logger.info("OK, creating connection and starting to transmit"); - tryCreateTransmission(transmission, member, probData[1]); - } else if (probData[1] > 100) { // TODO Impossible value, what should it be?! - // Transmission is only interference at destination - tryCreateInterference(transmission, member, probData[1]); - } else { - //logger.info("Signal to low to be considered interference"); - } - } - } - - } - }; - - - /** - * Creates a new Advanced Radio Medium (ARM). - */ - public AdvancedRadioMedium() { - - // Create the channel model - currentChannelModel = new ChannelModel(); - - // Register temporary plugins - logger.info("Registering ARM plugins"); - GUI.currentGUI.registerTemporaryPlugin(AreaViewer.class); - GUI.currentGUI.registerTemporaryPlugin(FormulaViewer.class); - } - - // -- Radio Medium standard methods -- - - public void registerMote(Mote mote, Simulation sim) { - registerRadioInterface(mote.getInterfaces().getRadio(), mote.getInterfaces().getPosition(), sim); - } - - public void unregisterMote(Mote mote, Simulation sim) { - unregisterRadioInterface(mote.getInterfaces().getRadio(), sim); - } - - public void registerRadioInterface(Radio radio, Position position, Simulation sim) { - if (radio == null || position == null) { - logger.fatal("Could not register radio: " + radio + " @ " + position); - return; - } - - // If we are not already tick observering simulation, we should be - if (simulationObserver == null) { - mySimulation = sim; - simulationObserver = new Observer() { - public void update(Observable obs, Object obj) { - // Check if any transmission is active in the radio medium - if (allTransmissions.isEmpty()) - return; - - Vector uncompletedTransmissions = new Vector(); - Vector completedTransmissions = new Vector(); - - // Check if any transmission has completed - for (RadioTransmission transmission: allTransmissions) { - if (transmission.isCompleted()) { - completedTransmissions.add(transmission); - } else { - uncompletedTransmissions.add(transmission); - } - } - - if (completedTransmissions.isEmpty()) - // Nothing to do - return; - - // At least one transmission has completed - deliver data for associated transfers - for (RadioTransmission transmission: completedTransmissions) { - // Unregister interferences of this transmission source - Vector intfToUnregister = new Vector(); - for (RadioInterference interference: allInterferences) { - if (interference.mySource == transmission) { - intfToUnregister.add(interference); - } - } - for (RadioInterference interference: intfToUnregister) - unregisterInterference(interference); - - // Deliver data and unregister transmission - Vector transToUnregister = new Vector(); - for (RadioTransfer transfer: allTransfers) { - if (transfer.mySource == transmission) { - if (!transfer.interferenceDestroyedConnection()) { - // Don't interfer connection - } else { - transfer.myDestination.radio.interferReception(0); - } - transToUnregister.add(transfer); - } - } - for (RadioTransfer transfer: transToUnregister) - unregisterTransmission(transfer); - } - - allTransmissions = uncompletedTransmissions; - radioActivityObservable.notifyRadioActivityChanged(); // Need to notify observers - - // Update all radio signal strengths - for (ARMMember member: registeredMembers) { - member.updateHeardSignalStrength(); - } - } - }; - - sim.addTickObserver(simulationObserver); - } - - // Save both radio and its position, and also register us as an observer to the radio - ARMMember member = new ARMMember(radio, position); - registeredMembers.add(member); - radio.addObserver(radioObserver); - radio.setCurrentSignalStrength(currentChannelModel.getParameterDoubleValue(("bg_noise_mean"))); - - // Settings have changed - notify observers - settingsObservable.notifySettingsChanged(); - } - - public void unregisterRadioInterface(Radio radioToRemove, Simulation sim) { - // Find corresponding radio member and remove it - ARMMember memberToRemove = null; - for (ARMMember member: registeredMembers) { - if (member.radio == radioToRemove) { - memberToRemove = member; - break; - } - } - - if (memberToRemove != null) { - registeredMembers.remove(memberToRemove); - } else - logger.warn("ARM: Could not unregister radio: " + radioToRemove); - - // Settings have changed - notify observers - settingsObservable.notifySettingsChanged(); - } - - public void addRadioMediumObserver(Observer observer) { - // Add radio traffic observer to this radio medium - radioActivityObservable.addObserver(observer); - } - - public void deleteRadioMediumObserver(Observer observer) { - // Remove observer from this radio medium - radioActivityObservable.deleteObserver(observer); - } - - public RadioConnection[] getLastTickConnections() { - logger.fatal("ARM: getLastTickConnections() not implemented"); - return null; - } - - public void setConnectionLogger(ConnectionLogger connection) { - logger.fatal("ARM: setConnectionLogger() not implemented"); - } - - public Collection getConfigXML() { - // Just forwarding to current channel model - return currentChannelModel.getConfigXML(); - } - - public boolean setConfigXML(Collection configXML) { - // Just forwarding to current channel model - return currentChannelModel.setConfigXML(configXML); - } - - - // -- Advanced Radio Medium specific methods -- - - /** - * Adds an observer which is notified when this radio medium has - * changed settings, such as added or removed radios. - * - * @param obs New observer - */ - public void addSettingsObserver(Observer obs) { - settingsObservable.addObserver(obs); - } - - /** - * Deletes an earlier registered setting observer. - * - * @param osb - * Earlier registered observer - */ - public void deleteSettingsObserver(Observer obs) { - settingsObservable.deleteObserver(obs); - } - - /** - * Returns position of given radio. - * - * @param radio Registered radio - * @return Position of given radio - */ - public Position getRadioPosition(Radio radio) { - // Find radio, and return its position - for (ARMMember member: registeredMembers) { - if (member.radio == radio) { - return member.position; - } - } - logger.fatal("ARM: Given radio is not registered!"); - return null; - } - - /** - * @return Number of registered radios. - */ - public int getRegisteredRadioCount() { - return registeredMembers.size(); - } - - /** - * Returns radio at given index. - * - * @param index Index of registered radio. - * @return Radio at given index - */ - public Radio getRegisteredRadio(int index) { - return registeredMembers.get(index).radio; - } - - /** - * Returns the current channel model object, responsible for - * all probability and transmission calculations. - * - * @return Current channel model - */ - public ChannelModel getChannelModel() { - return currentChannelModel; - } - - - - /** - * Tries to create a new transmission between given transmission and - * destination. The given signal strength should be the incoming signal - * strength at the destination. This value will be used after the transmission - * is completed in order to compare the connection with any interference. - * - * @param source - * @param destination - * @param signalStrength - * @return - */ - public void tryCreateTransmission(RadioTransmission source, ARMMember destination, double signalStrength) { - // Check if destination is already listening to a connection - if (destination.isListeningOnTransmission()) { - RadioInterference newInterference = new RadioInterference(source, destination, signalStrength); - destination.heardInterferences.add(newInterference); - - registerInterference(newInterference); - return; - } - - // Create new transmission - RadioTransfer newTransmission = new RadioTransfer(source, destination, signalStrength); - destination.heardTransmission = newTransmission; - - registerTransmission(newTransmission); - } - - public void tryCreateInterference(RadioTransmission source, ARMMember destination, double signalStrength) { - RadioInterference newInterference = new RadioInterference(source, destination, signalStrength); - destination.heardInterferences.add(newInterference); - - registerInterference(newInterference); - } - - - /** - * ARM radio transmission. - */ - class RadioTransmission { - ARMMember source = null; - int endTime = 0; - byte[] dataToTransfer = null; - - public RadioTransmission(ARMMember source, int endTime, byte[] dataToTransfer) { - this.source = source; - - this.endTime = endTime; - - this.dataToTransfer = dataToTransfer; - } - - /** - * @return True if no longer transmitting. - */ - public boolean isCompleted() { - return mySimulation.getSimulationTime() >= endTime; - } - - - } - - /** - * ARM radio interference - */ - class RadioInterference { - RadioTransmission mySource; - ARMMember myDestination; - double interferenceSignalStrength; - - public RadioInterference(RadioTransmission transmission, ARMMember destination, double signalStrength) { - this.mySource = transmission; - this.myDestination = destination; - this.interferenceSignalStrength = signalStrength; - } - - /** - * @return True if interference is no more. - */ - public boolean isOld() { - return mySource.isCompleted(); - } - - } - - /** - * ARM radio transfers - */ - class RadioTransfer { - RadioTransmission mySource; - ARMMember myDestination; - double transmissionSignalStrength; - double maxInterferenceSignalStrength; - - public RadioTransfer(RadioTransmission source, ARMMember destination, double signalStrength) { - this.mySource = source; - this.myDestination = destination; - this.transmissionSignalStrength = signalStrength; - maxInterferenceSignalStrength = -Double.MAX_VALUE; - - destination.radio.receivePacket(source.dataToTransfer, source.endTime); - destination.radio.setCurrentSignalStrength(signalStrength); - } - - public void addInterference(double signalStrength) { - if (signalStrength > maxInterferenceSignalStrength) { - maxInterferenceSignalStrength = signalStrength; - } - myDestination.radio.setCurrentSignalStrength(Math.max( - maxInterferenceSignalStrength, transmissionSignalStrength)); - } - - /** - * @return True if transmission is completed. - */ - public boolean isOld() { - return mySource.isCompleted(); - } - - /** - * @return True if interference destroyed transmission - */ - public boolean interferenceDestroyedConnection() { - if (maxInterferenceSignalStrength + 30 > transmissionSignalStrength) { - // Recalculating probability of delivery - double[] probData = currentChannelModel.getProbability( - mySource.source.position.getXCoordinate(), - mySource.source.position.getYCoordinate(), - myDestination.position.getXCoordinate(), - myDestination.position.getYCoordinate(), - maxInterferenceSignalStrength); -// logger.info("Transfer was interfered, recalculating probability of success: " + probData[0]); - - if (new Random().nextFloat() >= probData[0]) { - return true; - } - } - - return false; - } - } - - /** - * Inner class used for keeping track transceivers. - */ - class ARMMember { - Radio radio = null; - Position position = null; - - private RadioTransfer heardTransmission; - private Vector heardInterferences = new Vector(); - double currentSignalStrength = -Double.MAX_VALUE; - - public ARMMember(Radio radio, Position position) { - this.radio = radio; - this.position = position; - } - - public boolean isListeningOnTransmission() { - if (heardTransmission == null) - return false; - - if (heardTransmission.isOld()) { - heardTransmission = null; - } - - return heardTransmission != null; - } - - /** - * Calculates current incoming signal strength at this radio. - * Observe, does not alter any transmissions! - */ - public void updateHeardSignalStrength() { - double maxSignalStrength = -Double.MAX_VALUE; - - // Get maximum interference and also update interference list - Vector newInterferences = new Vector(); - for (RadioInterference interference: heardInterferences) { - if (!interference.isOld()) { - newInterferences.add(interference); - maxSignalStrength = Math.max(maxSignalStrength, - interference.interferenceSignalStrength); - } - } - heardInterferences = newInterferences; - - if (heardTransmission != null && !heardTransmission.isOld()) { - maxSignalStrength = Math.max(maxSignalStrength, - heardTransmission.transmissionSignalStrength); - } else - heardTransmission = null; - - // Noise level - maxSignalStrength = Math.max(maxSignalStrength, currentChannelModel - .getParameterDoubleValue("bg_noise_mean")); - - currentSignalStrength = maxSignalStrength; - radio.setCurrentSignalStrength(currentSignalStrength); - } - - } - - - public void registerInterference(RadioInterference interference) { - allInterferences.add(interference); - - updateInterferences(); - radioActivityObservable.notifyRadioActivityChanged(); // Need to notify observers - } - - public void registerTransmission(RadioTransfer transmission) { - allTransfers.add(transmission); - - updateInterferences(); - radioActivityObservable.notifyRadioActivityChanged(); // Need to notify observers - } - - public void unregisterInterference(RadioInterference interference) { - updateInterferences(); - - allInterferences.remove(interference); - radioActivityObservable.notifyRadioActivityChanged(); // Need to notify observers - } - - public void unregisterTransmission(RadioTransfer transmission) { - updateInterferences(); - - allTransfers.remove(transmission); - radioActivityObservable.notifyRadioActivityChanged(); // Need to notify observers - } - - private void updateInterferences() { - // We need to check impact of interferences on transmissions - for (RadioTransfer transmission: allTransfers) { - for (RadioInterference interference: allInterferences) { - if (interference.myDestination == transmission.myDestination) { - transmission.addInterference(interference.interferenceSignalStrength); - } - } - } - } - - class TransmissionsObservable extends Observable { - private void notifyRadioActivityChanged() { - setChanged(); - notifyObservers(); - } - } - - class SettingsObservable extends Observable { - private void notifySettingsChanged() { - setChanged(); - notifyObservers(); - } - } - - /** - * @return Current active transmissions - */ - public Vector getCurrentTransmissions() { - return allTransmissions; - } - - /** - * @return Current active transmissions - */ - public RadioTransmission[] getCurrentTransmissionsArray() { - return allTransmissions.toArray(new RadioTransmission[0]); - } - - /** - * @return Current active interferences - */ - public Vector getCurrentInterferences() { - return allInterferences; - } - - /** - * @return Current active interferences - */ - public RadioInterference[] getCurrentInterferencesArray() { - return allInterferences.toArray(new RadioInterference[0]); - } - - /** - * @return Current active transfers - */ - public Vector getCurrentTransfers() { - return allTransfers; - } - - /** - * @return Current active transfers - */ - public RadioTransfer[] getCurrentTransfersArray() { - return allTransfers.toArray(new RadioTransfer[0]); - } - - - - -} diff --git a/tools/cooja/apps/arm/java/se/sics/arm/AngleInterval.java b/tools/cooja/apps/arm/java/se/sics/arm/AngleInterval.java deleted file mode 100644 index bdd85ffa6..000000000 --- a/tools/cooja/apps/arm/java/se/sics/arm/AngleInterval.java +++ /dev/null @@ -1,385 +0,0 @@ -package se.sics.arm; - -import java.awt.geom.Line2D; -import java.awt.geom.Point2D; -import java.util.Vector; - -import org.apache.log4j.Logger; - -/** - * This class represents an angle interval. - * - * @author Fredrik Osterlind - */ -class AngleInterval { - private static Logger logger = Logger.getLogger(AngleInterval.class); - - // Sub intervals all between 0 and 2*PI - Vector subIntervals; - - /** - * Creates a new angle interval. - * - * @param startAngle Start angle (rad) - * @param endAngle End angle (rad) (> start angle) - */ - public AngleInterval(double startAngle, double endAngle) { - subIntervals = new Vector(); - - if (endAngle < startAngle) { - - } else if (endAngle - startAngle >= 2*Math.PI) { - subIntervals.add(new Interval(0, 2*Math.PI)); - } else { - while (startAngle < 0) - startAngle += 2*Math.PI; - while (endAngle < 0) - endAngle += 2*Math.PI; - startAngle %= 2*Math.PI; - endAngle %= 2*Math.PI; - - Interval tempInterval; - if (startAngle < endAngle) { - tempInterval = new Interval(startAngle, endAngle); - if (!tempInterval.isEmpty()) - subIntervals.add(tempInterval); - } else { - tempInterval = new Interval(startAngle, 2*Math.PI); - if (!tempInterval.isEmpty()) - subIntervals.add(tempInterval); - tempInterval = new Interval(0, endAngle); - if (!tempInterval.isEmpty()) - subIntervals.add(tempInterval); - } - } - } - - /** - * Returns new intervals consisting of this interval with the given interval removed. - * These can either be null (if entire interval was removed), - * one interval (if upper or lower part, or nothing was removed) or two intervals - * (if middle part of interval was removed). - * - * @param intervalToSubtract Other interval - * @return New intervals - */ - public Vector subtract(AngleInterval intervalToSubtract) { - Vector afterSubtractionIntervals = new Vector(); - - // Before subtraction - afterSubtractionIntervals.addAll(subIntervals); - - if (intervalToSubtract == null) { - Vector ret = new Vector(); - ret.add(this); - return ret; - } - - // Subtract every subinterval each - for (int i=0; i < intervalToSubtract.subIntervals.size(); i++) { - Interval subIntervalToSubtract = intervalToSubtract.subIntervals.get(i); - Vector newAfterSubtractionIntervals = new Vector(); - - for (int j=0; j < afterSubtractionIntervals.size(); j++) { - Vector tempIntervals = afterSubtractionIntervals.get(j).subtract(subIntervalToSubtract); - if (tempIntervals != null) - newAfterSubtractionIntervals.addAll(tempIntervals); - } - - afterSubtractionIntervals = newAfterSubtractionIntervals; - } - - Vector newAngleIntervals = new Vector(); - for (int i=0; i < afterSubtractionIntervals.size(); i++) { - if (afterSubtractionIntervals.get(i) != null && !afterSubtractionIntervals.get(i).isEmpty()) - newAngleIntervals.add( - new AngleInterval(afterSubtractionIntervals.get(i).getLow(), afterSubtractionIntervals.get(i).getHigh()) - ); - } - - return newAngleIntervals; - } - - /** - * Returns the intersection of this interval with - * the given. - * - * @param interval Other interval - * @return Intersection - */ - public AngleInterval intersectWith(AngleInterval interval) { - Vector afterIntersectionIntervals = new Vector(); - - // Intersect all subintervals, keep all results - for (int i=0; i < interval.subIntervals.size(); i++) { - for (int j=0; j < subIntervals.size(); j++) { - Interval temp = interval.subIntervals.get(i).intersectWith(subIntervals.get(j)); - if (temp != null && !temp.isEmpty()) - afterIntersectionIntervals.add(temp); - } - } - - if (afterIntersectionIntervals.size() > 2) { - logger.fatal("AngleInterval.intersectWith() error!"); - } else if (afterIntersectionIntervals.size() == 2) { - - // The interval (y-x) is divided into: - // y -> 2*PI - // 0 -> x - Interval interval1 = afterIntersectionIntervals.get(0); - Interval interval2 = afterIntersectionIntervals.get(1); - - if (interval1.getLow() == 0) - return new AngleInterval( - interval2.getLow(), interval1.getHigh() + 2*Math.PI - ); - else - return new AngleInterval( - interval1.getLow(), interval2.getHigh() + 2*Math.PI - ); - - } else if (afterIntersectionIntervals.size() == 1) { - return new AngleInterval( - afterIntersectionIntervals.firstElement().getLow(), - afterIntersectionIntervals.firstElement().getHigh() - ); - } - - return null; - } - - /** - * Returns start angle of this interval. - * This angle is always > 0 and < the end angle. - * - * @return Start angle - */ - public double getStartAngle() { - if (subIntervals == null || subIntervals.isEmpty()) { - logger.warn("Getting start angle of null angle interval!"); - return 0; - } - - if (subIntervals.size() > 2) { - logger.warn("Getting start angle of malformed angle interval!"); - return 0; - } - - if (subIntervals.size() == 1) { - return subIntervals.firstElement().getLow(); - } - - // The interval (y-x) is divided into: - // y -> 2*PI - // 0 -> x - Interval interval1 = subIntervals.get(0); - Interval interval2 = subIntervals.get(1); - - if (interval1.getLow() == 0) - return interval2.getLow(); - else - return interval1.getLow(); - } - - /** - * Returns end angle of this interval. - * This angle is always > start angle, and may be > 2*PI. - * - * @return End angle - */ - public double getEndAngle() { - if (subIntervals == null || subIntervals.isEmpty()) { - logger.warn("Getting start angle of null angle interval!"); - return 0; - } - - if (subIntervals.size() > 2) { - logger.warn("Getting start angle of malformed angle interval!"); - return 0; - } - - if (subIntervals.size() == 1) { - return subIntervals.firstElement().getHigh(); - } - - // The interval (y-x) is divided into: - // y -> 2*PI - // 0 -> x - Interval interval1 = subIntervals.get(0); - Interval interval2 = subIntervals.get(1); - - if (interval1.getLow() == 0) - return interval1.getHigh() + 2*Math.PI; - else - return interval2.getHigh() + 2*Math.PI; - } - - /** - * @return Size of interval (rad) - */ - public double getSize() { - double size = 0; - for (int i=0; i < subIntervals.size(); i++) - size += subIntervals.get(i).getSize(); - - return size; - } - - /** - * Checks if the given interval is a subset of this interval. - * - * @param interval Other interval - * @return True if this interval contains given interval - */ - public boolean contains(AngleInterval interval) { - // Check that all parts of argument is contained by any part of this - for (int i=0; i < interval.subIntervals.size(); i++) { - boolean contained = false; - for (int j=0; j < subIntervals.size(); j++) { - if (subIntervals.get(j).contains(interval.subIntervals.get(i))) { - contained = true; - break; - } - } - if (!contained) - return false; - } - return true; - } - - /** - * Checks if the two intervals intersect. - * - * @param interval Other interval - * @return True if this interval intersects given interval - */ - public boolean intersects(AngleInterval interval) { - return (intersectWith(interval) != null); - } - - /** - * @return True if interval defined is of no size. - */ - public boolean isEmpty() { - if (subIntervals.isEmpty()) - return true; - if (getSize() <= 0.001) - return true; - return false; - } - - public String toString() { - String retString = ""; - for (int i=0; i < subIntervals.size(); i++) { - if (!retString.equals("")) - retString = retString.concat(" && "); - - retString = retString.concat("("); - retString = retString.concat(Math.toDegrees(subIntervals.get(i).getLow()) + " -> " + Math.toDegrees(subIntervals.get(i).getHigh())); - retString = retString.concat(")"); - } - - return retString; - } - - /** - * Returns a line starting at given start point and - * in the given direction. - * This line may be used when calculating intersection points. - * - * @param startPoint Start point - * @param angle Line direction (rad) - * @return Line - */ - public static Line2D getDirectedLine(Point2D startPoint, double angle, double length) { - return new Line2D.Double( - startPoint.getX(), - startPoint.getY(), - startPoint.getX() + length*Math.cos(angle), - startPoint.getY() + length*Math.sin(angle) - ); - } - - /** - * Returns an angle interval of the given line seen from - * the given reference point. - * - * @param refPoint Reference point - * @param line Line to measure angle against - * @return Angle interval (-pi <-> pi) - */ - public static AngleInterval getAngleIntervalOfLine(Point2D refPoint, Line2D line) { - // Create angle interval of this line - double x1 = line.getX1() - refPoint.getX(); - double y1 = line.getY1() - refPoint.getY(); - double x2 = line.getX2() - refPoint.getX(); - double y2 = line.getY2() - refPoint.getY(); - - double angle1 = Math.atan2(y1, x1); - double angle2 = Math.atan2(y2, x2); - - // If interval is bigger than PI, line angles must wrap - if (Math.abs(angle1 - angle2) > Math.PI) { - if (angle1 < 0) - angle1 += 2*Math.PI; - else - angle2 += 2*Math.PI; - } - - return new AngleInterval( - Math.min(angle1, angle2), Math.max(angle1, angle2) - ); - } - - public boolean equals(Object object) { - if (object == null) - return false; - - AngleInterval interval = (AngleInterval) object; - return (interval.getStartAngle() == this.getStartAngle() && interval.getEndAngle() == this.getEndAngle()); - } - - /** - * Subtracts given interval from all intervals in given vector. - * This method never returns null (but empty vectors). - * - * @param initialIntervals Initial intervals - * @param interval Interval to subtract - * @return New intervals - */ - public static Vector subtract(Vector initialIntervals, AngleInterval interval) { - Vector newIntervals = new Vector(); - - for (int i=0; i < initialIntervals.size(); i++) { - Vector tempIntervals = initialIntervals.get(i).subtract(interval); - if (tempIntervals != null) { - newIntervals.addAll(tempIntervals); - } - } - - return newIntervals; - } - - /** - * Intersects given interval with all intervals in given vector. - * This method never returns null (but empty vectors). - * - * @param initialIntervals Initial intervals - * @param interval Interval to intersect - * @return New intervals - */ - public static Vector intersect(Vector initialIntervals, AngleInterval interval) { - Vector newIntervals = new Vector(); - - for (int i=0; i < initialIntervals.size(); i++) { - AngleInterval tempInterval = initialIntervals.get(i).intersectWith(interval); - if (tempInterval != null) { - newIntervals.add(tempInterval); - } - } - - return newIntervals; - } - - -} diff --git a/tools/cooja/apps/arm/java/se/sics/arm/AreaViewer.java b/tools/cooja/apps/arm/java/se/sics/arm/AreaViewer.java deleted file mode 100644 index aab1fd870..000000000 --- a/tools/cooja/apps/arm/java/se/sics/arm/AreaViewer.java +++ /dev/null @@ -1,2186 +0,0 @@ -package se.sics.arm; - -import java.awt.*; -import java.awt.event.*; -import java.awt.geom.*; -import java.awt.image.BufferedImage; -import java.io.File; -import java.net.URL; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.*; -import javax.swing.*; -import javax.swing.filechooser.FileFilter; -import org.apache.log4j.Logger; -import org.jdom.Element; - -import se.sics.cooja.*; -import se.sics.cooja.interfaces.*; -import se.sics.arm.AdvancedRadioMedium.*; - -/** - * The class AreaViewer belongs to the Advanced Radio Medium (ARM) package. - * - * It is used to visualize available radios, traffic between them as well - * as the current radio propagation area of single radios. - * Users may also add background images (such as maps) and color-analyze them - * in order to add simulated obstacles in the radio medium. - * - * For more information about ARM see @link AdvancedRadioMedium. - * - * @see AdvancedRadioMedium - * @author Fredrik Osterlind - */ -@ClassDescription("ARM - Area Viewer") -@VisPluginType(VisPluginType.SIM_PLUGIN) -public class AreaViewer extends VisPlugin { - private static final long serialVersionUID = 1L; - private static Logger logger = Logger.getLogger(AreaViewer.class); - - private final JPanel canvas; - private final VisPlugin thisPlugin; - - ChannelModel.TransmissionData dataTypeToVisualize = ChannelModel.TransmissionData.SIGNAL_STRENGTH; - ButtonGroup visTypeSelectionGroup; - - // General drawing parameters - private Point lastHandledPosition = new Point(0,0); - private double zoomCenterX = 0.0; - private double zoomCenterY = 0.0; - private Point zoomCenterPoint = new Point(); - private double currentZoomX = 1.0f; - private double currentZoomY = 1.0f; - private double currentPanX = 0.0f; - private double currentPanY = 0.0f; - - private boolean drawBackgroundImage = true; - private boolean drawCalculatedObstacles = true; - private boolean drawChannelProbabilities = true; - private boolean drawRadios = true; - private boolean drawRadioActivity = true; - private boolean drawScaleArrow = true; - - // Background drawing parameters (meters) - private double backgroundStartX = 0.0; - private double backgroundStartY = 0.0; - private double backgroundWidth = 0.0; - private double backgroundHeight = 0.0; - private Image backgroundImage = null; - private File backgroundImageFile = null; - - // Obstacle drawing parameters (same scale as background) - private boolean needToRepaintObstacleImage = false; - private double obstacleStartX = 0.0; - private double obstacleStartY = 0.0; - private double obstacleWidth = 0.0; - private double obstacleHeight = 0.0; - private Image obstacleImage = null; - - // Channel probabilities drawing parameters (meters) - private double channelStartX = 0.0; - private double channelStartY = 0.0; - private double channelWidth = 0.0; - private double channelHeight = 0.0; - private Image channelImage = null; - - private JSlider resolutionSlider; - private JPanel controlPanel; - private JScrollPane scrollControlPanel; - - private Simulation currentSimulation; - private AdvancedRadioMedium currentRadioMedium; - private ChannelModel currentChannelModel; - - private final String antennaImageFilename = "antenna.png"; - private final Image antennaImage; - - private Radio selectedRadio = null; - private boolean inSelectMode = true; - private boolean inTrackMode = false; - - private Vector trackedComponents = null; - - // Coloring variables - private JPanel coloringIntervalPanel = null; - private double coloringHighest = 0; - private double coloringLowest = 0; - private boolean coloringIsFixed = true; - - private Thread attenuatorThread = null; - - private JCheckBox showSettingsBox; - private JCheckBox backgroundCheckBox; - private JCheckBox obstaclesCheckBox; - private JCheckBox channelCheckBox; - private JCheckBox radiosCheckBox; - private JCheckBox radioActivityCheckBox; - private JCheckBox arrowCheckBox; - - /** - * Initializes an AreaViewer. - * - * @param simulationToVisualize Simulation using Advanced Radio Medium - */ - public AreaViewer(Simulation simulationToVisualize) { - super("Advanced Radio Medium - Area Viewer"); - - currentSimulation = simulationToVisualize; - currentRadioMedium = (AdvancedRadioMedium) currentSimulation.getRadioMedium(); - currentChannelModel = currentRadioMedium.getChannelModel(); - - // We want to listen to changes both in the channel model as well as in the radio medium - currentChannelModel.addSettingsObserver(channelModelSettingsObserver); - currentRadioMedium.addSettingsObserver(radioMediumSettingsObserver); - currentRadioMedium.addRadioMediumObserver(radioMediumActivityObserver); - - // Set initial size etc. - setSize(500, 500); - setVisible(true); - thisPlugin = this; - - // Canvas mode radio buttons + show settings checkbox - showSettingsBox = new JCheckBox ("settings", true); - showSettingsBox.setAlignmentY(Component.TOP_ALIGNMENT); - showSettingsBox.setContentAreaFilled(false); - showSettingsBox.setActionCommand("toggle show settings"); - showSettingsBox.addActionListener(canvasModeHandler); - - JRadioButton selectModeButton = new JRadioButton ("select"); - selectModeButton.setAlignmentY(Component.BOTTOM_ALIGNMENT); - selectModeButton.setContentAreaFilled(false); - selectModeButton.setActionCommand("set select mode"); - selectModeButton.addActionListener(canvasModeHandler); - selectModeButton.setSelected(true); - - JRadioButton panModeButton = new JRadioButton ("pan"); - panModeButton.setAlignmentY(Component.BOTTOM_ALIGNMENT); - panModeButton.setContentAreaFilled(false); - panModeButton.setActionCommand("set pan mode"); - panModeButton.addActionListener(canvasModeHandler); - - JRadioButton zoomModeButton = new JRadioButton ("zoom"); - zoomModeButton.setAlignmentY(Component.BOTTOM_ALIGNMENT); - zoomModeButton.setContentAreaFilled(false); - zoomModeButton.setActionCommand("set zoom mode"); - zoomModeButton.addActionListener(canvasModeHandler); - - JRadioButton trackModeButton = new JRadioButton ("track rays"); - trackModeButton.setAlignmentY(Component.BOTTOM_ALIGNMENT); - trackModeButton.setContentAreaFilled(false); - trackModeButton.setActionCommand("set track rays mode"); - trackModeButton.addActionListener(canvasModeHandler); - - ButtonGroup group = new ButtonGroup(); - group.add(selectModeButton); - group.add(panModeButton); - group.add(zoomModeButton); - group.add(trackModeButton); - - // Create canvas - canvas = new JPanel() { - private static final long serialVersionUID = 1L; - public void paintComponent(Graphics g) { - super.paintComponent(g); - repaintCanvas((Graphics2D) g); - } - }; - canvas.setBorder(BorderFactory.createLineBorder(Color.BLACK)); - canvas.setBackground(Color.WHITE); - canvas.setLayout(new BorderLayout()); - canvas.addMouseListener(canvasMouseHandler); - - // Create canvas mode panel - JPanel canvasModePanel = new JPanel(); - canvasModePanel.setOpaque(false); - canvasModePanel.setLayout(new BoxLayout(canvasModePanel, BoxLayout.Y_AXIS)); - canvasModePanel.setAlignmentY(Component.BOTTOM_ALIGNMENT); - canvasModePanel.add(showSettingsBox); - canvasModePanel.add(Box.createVerticalGlue()); - canvasModePanel.add(selectModeButton); - canvasModePanel.add(panModeButton); - canvasModePanel.add(zoomModeButton); - canvasModePanel.add(trackModeButton); - canvas.add(BorderLayout.EAST, canvasModePanel); - - // Create control graphics panel - JPanel graphicsComponentsPanel = new JPanel(); - graphicsComponentsPanel.setLayout(new BoxLayout(graphicsComponentsPanel, BoxLayout.Y_AXIS)); - graphicsComponentsPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); - graphicsComponentsPanel.setAlignmentX(Component.CENTER_ALIGNMENT); - - graphicsComponentsPanel.add(new JLabel("Show components:")); - - backgroundCheckBox = new JCheckBox("Background", true); - backgroundCheckBox.setActionCommand("toggle background"); - backgroundCheckBox.addActionListener(selectGraphicsHandler); - graphicsComponentsPanel.add(backgroundCheckBox); - - obstaclesCheckBox = new JCheckBox("Obstacles", true); - obstaclesCheckBox.setActionCommand("toggle obstacles"); - obstaclesCheckBox.addActionListener(selectGraphicsHandler); - graphicsComponentsPanel.add(obstaclesCheckBox); - - channelCheckBox = new JCheckBox("Channel probability", true); - channelCheckBox.setActionCommand("toggle channel"); - channelCheckBox.addActionListener(selectGraphicsHandler); - graphicsComponentsPanel.add(channelCheckBox); - - radiosCheckBox = new JCheckBox("Radios", true); - radiosCheckBox.setActionCommand("toggle radios"); - radiosCheckBox.addActionListener(selectGraphicsHandler); - graphicsComponentsPanel.add(radiosCheckBox); - - radioActivityCheckBox = new JCheckBox("Radio Activity", true); - radioActivityCheckBox.setActionCommand("toggle radio activity"); - radioActivityCheckBox.addActionListener(selectGraphicsHandler); - graphicsComponentsPanel.add(radioActivityCheckBox); - - arrowCheckBox = new JCheckBox("Scale arrow", true); - arrowCheckBox.setActionCommand("toggle arrow"); - arrowCheckBox.addActionListener(selectGraphicsHandler); - graphicsComponentsPanel.add(arrowCheckBox); - - graphicsComponentsPanel.add(Box.createRigidArea(new Dimension(0,20))); - graphicsComponentsPanel.add(new JLabel("Configure attenuating obstacles:")); - - JButton addBackgroundButton = new JButton("Set background image"); - addBackgroundButton.setActionCommand("set background image"); - addBackgroundButton.addActionListener(setBackgroundHandler); - graphicsComponentsPanel.add(addBackgroundButton); - - JButton analyzeObstaclesButton = new JButton("Analyze background for obstacles"); - analyzeObstaclesButton.setActionCommand("analyze for obstacles"); - analyzeObstaclesButton.addActionListener(analyzeObstaclesHandler); - graphicsComponentsPanel.add(analyzeObstaclesButton); - - // Create visualize channel output panel - JPanel visualizeChannelPanel = new JPanel(); - visualizeChannelPanel.setLayout(new BoxLayout(visualizeChannelPanel, BoxLayout.Y_AXIS)); - visualizeChannelPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); - visualizeChannelPanel.setAlignmentX(Component.CENTER_ALIGNMENT); - - // Channel coloring intervals - visualizeChannelPanel.add(new JLabel("Color intervals:")); - - JRadioButton fixedColoringButton = new JRadioButton("Fixed channel coloring"); - fixedColoringButton.setSelected(true); - fixedColoringButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - coloringIsFixed = true; - } - }); - visualizeChannelPanel.add(fixedColoringButton); - - JRadioButton relativeColoringButton = new JRadioButton("Relative channel coloring"); - relativeColoringButton.setSelected(true); - relativeColoringButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - coloringIsFixed = false; - } - }); - visualizeChannelPanel.add(relativeColoringButton); - - ButtonGroup coloringGroup = new ButtonGroup(); - coloringGroup.add(fixedColoringButton); - coloringGroup.add(relativeColoringButton); - - coloringIntervalPanel = new JPanel() { - public void paintComponent(Graphics g) { - super.paintComponent(g); - - int width = getWidth(); - int height = getHeight(); - double diff = coloringHighest - coloringLowest; - int textHeight = g.getFontMetrics().getHeight(); - - // If computing - if (attenuatorThread != null && attenuatorThread.isAlive()) { - g.setColor(Color.WHITE); - g.fillRect(0, 0, width, height); - g.setColor(Color.BLACK); - String stringToDraw = "[calculating]"; - g.drawString(stringToDraw, width/2 - g.getFontMetrics().stringWidth(stringToDraw)/2, height/2 + textHeight/2); - return; - } - - // Check for infinite values - if (Double.isInfinite(coloringHighest) || Double.isInfinite(coloringLowest)) { - g.setColor(Color.WHITE); - g.fillRect(0, 0, width, height); - g.setColor(Color.BLACK); - String stringToDraw = "INFINITE VALUES EXIST"; - g.drawString(stringToDraw, width/2 - g.getFontMetrics().stringWidth(stringToDraw)/2, height/2 + textHeight/2); - return; - } - - // Check if values are constant - if (diff == 0) { - g.setColor(Color.WHITE); - g.fillRect(0, 0, width, height); - g.setColor(Color.BLACK); - NumberFormat formatter = DecimalFormat.getNumberInstance(); - String stringToDraw = "CONSTANT VALUES (" + formatter.format(coloringHighest) + ")"; - g.drawString(stringToDraw, width/2 - g.getFontMetrics().stringWidth(stringToDraw)/2, height/2 + textHeight/2); - return; - } - - for (int i=0; i < width; i++) { - double paintValue = coloringLowest + (double) i / (double) width * diff; - g.setColor( - new Color( - getColorOfSignalStrength(paintValue, coloringLowest, coloringHighest))); - - g.drawLine(i, 0, i, height); - } - - if (dataTypeToVisualize == ChannelModel.TransmissionData.PROB_OF_RECEPTION) { - NumberFormat formatter = DecimalFormat.getPercentInstance(); - g.setColor(Color.BLACK); - g.drawString(formatter.format(coloringLowest), 3, textHeight); - String stringToDraw = formatter.format(coloringHighest); - g.drawString(stringToDraw, width - g.getFontMetrics().stringWidth(stringToDraw) - 3, textHeight); - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.SIGNAL_STRENGTH || - dataTypeToVisualize == ChannelModel.TransmissionData.SIGNAL_STRENGTH_VAR ) { - NumberFormat formatter = DecimalFormat.getNumberInstance(); - g.setColor(Color.BLACK); - g.drawString(formatter.format(coloringLowest) + "dBm", 3, textHeight); - String stringToDraw = formatter.format(coloringHighest) + "dBm"; - g.drawString(stringToDraw, width - g.getFontMetrics().stringWidth(stringToDraw) - 3, textHeight); - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.SNR || - dataTypeToVisualize == ChannelModel.TransmissionData.SNR_VAR) { - NumberFormat formatter = DecimalFormat.getNumberInstance(); - g.setColor(Color.BLACK); - g.drawString(formatter.format(coloringLowest) + "dB", 3, textHeight); - String stringToDraw = formatter.format(coloringHighest) + "dB"; - g.drawString(stringToDraw, width - g.getFontMetrics().stringWidth(stringToDraw) - 3, textHeight); - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.DELAY_SPREAD_RMS) { - NumberFormat formatter = DecimalFormat.getNumberInstance(); - g.setColor(Color.BLACK); - g.drawString(formatter.format(coloringLowest) + "us", 3, textHeight); - String stringToDraw = formatter.format(coloringHighest) + "us"; - g.drawString(stringToDraw, width - g.getFontMetrics().stringWidth(stringToDraw) - 3, textHeight); - } - - } - }; - coloringIntervalPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK)); - Dimension colorPanelSize = new Dimension(200, 20); - coloringIntervalPanel.setPreferredSize(colorPanelSize); - coloringIntervalPanel.setMinimumSize(colorPanelSize); - coloringIntervalPanel.setMaximumSize(colorPanelSize); - coloringIntervalPanel.setAlignmentX(Component.LEFT_ALIGNMENT); - visualizeChannelPanel.add(coloringIntervalPanel); - - // Choose channel output to visualize - visualizeChannelPanel.add(Box.createRigidArea(new Dimension(0,20))); - visualizeChannelPanel.add(new JLabel("Visualize radio output:")); - - JRadioButton signalStrengthButton = new JRadioButton("Signal strength"); - signalStrengthButton.setActionCommand("signalStrengthButton"); - signalStrengthButton.setSelected(true); - signalStrengthButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - dataTypeToVisualize = ChannelModel.TransmissionData.SIGNAL_STRENGTH; - } - }); - visualizeChannelPanel.add(signalStrengthButton); - - JRadioButton signalStrengthVarButton = new JRadioButton("Signal strength variance"); - signalStrengthVarButton.setActionCommand("signalStrengthVarButton"); - signalStrengthVarButton.setSelected(false); - signalStrengthVarButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - dataTypeToVisualize = ChannelModel.TransmissionData.SIGNAL_STRENGTH_VAR; - } - }); - visualizeChannelPanel.add(signalStrengthVarButton); - - JRadioButton SNRButton = new JRadioButton("Signal to Noise ratio"); - SNRButton.setActionCommand("SNRButton"); - SNRButton.setSelected(false); - SNRButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - dataTypeToVisualize = ChannelModel.TransmissionData.SNR; - } - }); - visualizeChannelPanel.add(SNRButton); - - JRadioButton SNRVarButton = new JRadioButton("Signal to Noise variance"); - SNRVarButton.setActionCommand("SNRVarButton"); - SNRVarButton.setSelected(false); - SNRVarButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - dataTypeToVisualize = ChannelModel.TransmissionData.SNR_VAR; - } - }); - visualizeChannelPanel.add(SNRVarButton); - - JRadioButton probabilityButton = new JRadioButton("Probability of reception"); - probabilityButton.setActionCommand("probabilityButton"); - probabilityButton.setSelected(false); - probabilityButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - dataTypeToVisualize = ChannelModel.TransmissionData.PROB_OF_RECEPTION; - } - }); - visualizeChannelPanel.add(probabilityButton); - - JRadioButton rmsDelaySpreadButton = new JRadioButton("RMS delay spread"); - rmsDelaySpreadButton.setActionCommand("rmsDelaySpreadButton"); - rmsDelaySpreadButton.setSelected(false); - rmsDelaySpreadButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - dataTypeToVisualize = ChannelModel.TransmissionData.DELAY_SPREAD_RMS; - } - }); - visualizeChannelPanel.add(rmsDelaySpreadButton); - - visTypeSelectionGroup = new ButtonGroup(); - visTypeSelectionGroup.add(signalStrengthButton); - visTypeSelectionGroup.add(signalStrengthVarButton); - visTypeSelectionGroup.add(SNRButton); - visTypeSelectionGroup.add(SNRVarButton); - visTypeSelectionGroup.add(probabilityButton); - visTypeSelectionGroup.add(rmsDelaySpreadButton); - - visualizeChannelPanel.add(Box.createRigidArea(new Dimension(0,20))); - - visualizeChannelPanel.add(new JLabel("Image resolution:")); - - resolutionSlider = new JSlider(JSlider.HORIZONTAL, 30, 600, 200); - resolutionSlider.setMajorTickSpacing(100); - resolutionSlider.setPaintTicks(true); - resolutionSlider.setPaintLabels(true); - visualizeChannelPanel.add(resolutionSlider); - - visualizeChannelPanel.add(Box.createRigidArea(new Dimension(0,20))); - - JButton recalculateVisibleButton = new JButton("Recalculate visible area"); - recalculateVisibleButton.setActionCommand("recalculate visible area"); - recalculateVisibleButton.addActionListener(formulaHandler); - visualizeChannelPanel.add(recalculateVisibleButton); - - // Create control panel - controlPanel = new JPanel(); - controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS)); - controlPanel.add(graphicsComponentsPanel); - controlPanel.add(new JSeparator()); - controlPanel.add(Box.createRigidArea(new Dimension(0, 5))); - controlPanel.add(visualizeChannelPanel); - controlPanel.setPreferredSize(new Dimension(250,700)); - controlPanel.setAlignmentX(Component.CENTER_ALIGNMENT); - scrollControlPanel = new JScrollPane( - controlPanel, - JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, - JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - scrollControlPanel.setPreferredSize(new Dimension(250,0)); - - // Add everything - this.setLayout(new BorderLayout()); - this.add(BorderLayout.CENTER, canvas); // Add canvas - this.add(BorderLayout.EAST, scrollControlPanel); - - // Load external images (antenna) - Toolkit toolkit = Toolkit.getDefaultToolkit(); - URL imageURL = this.getClass().getClassLoader().getResource(antennaImageFilename); - antennaImage = toolkit.getImage(imageURL); - - MediaTracker tracker = new MediaTracker(canvas); - tracker.addImage(antennaImage, 1); - - try { - tracker.waitForAll(); - } catch (InterruptedException ex) { - logger.fatal("Interrupted during image loading, aborting"); - return; - } - - - // Try to select current plugin - try { - setSelected(true); - } catch (java.beans.PropertyVetoException e) { - // Could not select - } - } - - /** - * Listens to mouse event on canvas - */ - private MouseListener canvasMouseHandler = new MouseListener() { - public void mouseReleased(MouseEvent e) { - } - public void mouseExited(MouseEvent e) { - } - public void mouseClicked(MouseEvent e) { - if (inSelectMode) { - Vector hitRadios = trackClickedRadio(e.getPoint()); - - if (hitRadios == null || hitRadios.size() == 0) { - if (e.getButton() != MouseEvent.BUTTON1) { - selectedRadio = null; - channelImage = null; - canvas.repaint(); - } - return; - } - - if (hitRadios.size() == 1 && hitRadios.firstElement() == selectedRadio) - return; - - if (selectedRadio == null || !hitRadios.contains(selectedRadio)) { - selectedRadio = hitRadios.firstElement(); - } else { - // Select next in list - selectedRadio = hitRadios.get( - (hitRadios.indexOf(selectedRadio)+1) % hitRadios.size() - ); - } - - channelImage = null; - canvas.repaint(); - } else if (inTrackMode && selectedRadio != null) { - // Calculate real clicked position - double realClickedX = e.getX() / currentZoomX - currentPanX; - double realClickedY = e.getY() / currentZoomY - currentPanY; - - Position radioPosition = currentRadioMedium.getRadioPosition(selectedRadio); - final double radioX = radioPosition.getXCoordinate(); - final double radioY = radioPosition.getYCoordinate(); - - trackedComponents = currentChannelModel.getRaysOfTransmission(radioX, radioY, realClickedX, realClickedY); - - canvas.repaint(); - } - - } - public void mouseEntered(MouseEvent e) { - } - public void mousePressed(MouseEvent e) { - lastHandledPosition = new Point(e.getX(), e.getY()); - - // Set zoom center (real world) - zoomCenterX = e.getX() / currentZoomX - currentPanX; - zoomCenterY = e.getY() / currentZoomY - currentPanY; - zoomCenterPoint = e.getPoint(); - } - }; - - /** - * Listens to mouse movements when in pan mode - */ - private MouseMotionListener canvasPanModeHandler = new MouseMotionListener() { - public void mouseMoved(MouseEvent e) { - } - public void mouseDragged(MouseEvent e) { - if (lastHandledPosition == null) { - lastHandledPosition = e.getPoint(); - return; - } - - // Pan relative to mouse movement and current zoom - // This way the mouse "lock" to the canvas - currentPanX += ((float) (e.getX() - lastHandledPosition.x)) / currentZoomX; - currentPanY += ((float) (e.getY() - lastHandledPosition.y)) / currentZoomY; - lastHandledPosition = e.getPoint(); - - canvas.repaint(); - } - }; - - /** - * Listens to mouse movements when in zoom mode - */ - private MouseMotionListener canvasZoomModeHandler = new MouseMotionListener() { - public void mouseMoved(MouseEvent e) { - } - public void mouseDragged(MouseEvent e) { - if (lastHandledPosition == null) { - lastHandledPosition = e.getPoint(); - return; - } - - // Zoom relative to mouse movement (keep XY-proportions) - currentZoomY += 0.005 * currentZoomY * ((double) (lastHandledPosition.y - e.getY())); - currentZoomY = Math.max(0.05, currentZoomY); - currentZoomY = Math.min(1500, currentZoomY); - currentZoomX = currentZoomY; - - // We also need to update the current pan in order to zoom towards the mouse - currentPanX = zoomCenterPoint.x/currentZoomX - zoomCenterX; - currentPanY = zoomCenterPoint.y/currentZoomY - zoomCenterY; - - lastHandledPosition = e.getPoint(); - canvas.repaint(); - } - }; - - /** - * Selects which mouse mode the canvas should be in (select/pan/zoom) - */ - private ActionListener canvasModeHandler = new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("set select mode")) { - // Select mode, no mouse motion listener needed - for (MouseMotionListener reggedListener: canvas.getMouseMotionListeners()) - canvas.removeMouseMotionListener(reggedListener); - - inTrackMode = false; - inSelectMode = true; - } else if (e.getActionCommand().equals("set pan mode")) { - // Remove all other mouse motion listeners - for (MouseMotionListener reggedListener: canvas.getMouseMotionListeners()) - canvas.removeMouseMotionListener(reggedListener); - inSelectMode = false; - inTrackMode = false; - - // Add the special pan mouse motion listener - canvas.addMouseMotionListener(canvasPanModeHandler); - } else if (e.getActionCommand().equals("set zoom mode")) { - // Remove all other mouse motion listeners - for (MouseMotionListener reggedListener: canvas.getMouseMotionListeners()) - canvas.removeMouseMotionListener(reggedListener); - inSelectMode = false; - inTrackMode = false; - - // Add the special zoom mouse motion listener - canvas.addMouseMotionListener(canvasZoomModeHandler); - } else if (e.getActionCommand().equals("set track rays mode")) { - // Remove all other mouse motion listeners - for (MouseMotionListener reggedListener: canvas.getMouseMotionListeners()) - canvas.removeMouseMotionListener(reggedListener); - inSelectMode = false; - inTrackMode = true; - - } else if (e.getActionCommand().equals("toggle show settings")) { - if (((JCheckBox) e.getSource()).isSelected()) - scrollControlPanel.setVisible(true); - else - scrollControlPanel.setVisible(false); - thisPlugin.invalidate(); - thisPlugin.revalidate(); - - } - } - }; - - /** - * Selects which graphical parts should be painted - */ - private ActionListener selectGraphicsHandler = new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("toggle background")) - drawBackgroundImage = ((JCheckBox) e.getSource()).isSelected(); - else if (e.getActionCommand().equals("toggle obstacles")) - drawCalculatedObstacles = ((JCheckBox) e.getSource()).isSelected(); - else if (e.getActionCommand().equals("toggle channel")) - drawChannelProbabilities = ((JCheckBox) e.getSource()).isSelected(); - else if (e.getActionCommand().equals("toggle radios")) - drawRadios = ((JCheckBox) e.getSource()).isSelected(); - else if (e.getActionCommand().equals("toggle radio activity")) - drawRadioActivity = ((JCheckBox) e.getSource()).isSelected(); - else if (e.getActionCommand().equals("toggle arrow")) - drawScaleArrow = ((JCheckBox) e.getSource()).isSelected(); - - canvas.repaint(); - } - }; - - /** - * Helps user set a background image which can be analysed for obstacles/freespace. - */ - private ActionListener setBackgroundHandler = new ActionListener() { - - /** - * Choosable file filter that supports tif, gif, jpg, png, bmp. - */ - class ImageFilter extends FileFilter { - public boolean accept(File f) { - if (f.isDirectory()) { - return true; - } - - String filename = f.getName(); - if (filename != null) { - if (filename.endsWith(".tiff") || - filename.endsWith(".tif") || - filename.endsWith(".gif") || - filename.endsWith(".jpg") || - filename.endsWith(".jpeg") || - filename.endsWith(".png") || - filename.endsWith(".bmp")) { - return true; - } - } - return false; - } - - public String getDescription() { - return "All supported images"; - } - } - - class ImageSettingsDialog extends JDialog { - - private double - virtualStartX = 0.0, - virtualStartY = 0.0, - virtualWidth = 0.0, - virtualHeight = 0.0; - - private JFormattedTextField - virtualStartXField, - virtualStartYField, - virtualWidthField, - virtualHeightField; - - private boolean terminatedOK = false; - - private NumberFormat doubleFormat = NumberFormat.getNumberInstance(); - - /** - * Creates a new dialog for settings background parameters - */ - protected ImageSettingsDialog(File imageFile, Image image, Frame owner) { - super(owner, "Image settings"); - - JPanel tempPanel; - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - - // Set layout and add components - doubleFormat.setMinimumIntegerDigits(1); - setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS)); - - tempPanel = new JPanel(new GridLayout(1, 2)); - tempPanel.add(new JLabel("Start X (m) ")); - virtualStartXField = new JFormattedTextField(doubleFormat); - virtualStartXField.setValue(new Double(0.0)); - tempPanel.add(virtualStartXField); - add(tempPanel); - - tempPanel = new JPanel(new GridLayout(1, 2)); - tempPanel.add(new JLabel("Start Y (m)")); - virtualStartYField = new JFormattedTextField(doubleFormat); - virtualStartYField.setValue(new Double(0.0)); - tempPanel.add(virtualStartYField); - add(tempPanel); - - tempPanel = new JPanel(new GridLayout(1, 2)); - tempPanel.add(new JLabel("Width (m)")); - virtualWidthField = new JFormattedTextField(doubleFormat); - virtualWidthField.setValue(new Double(100.0)); - tempPanel.add(virtualWidthField); - add(tempPanel); - - tempPanel = new JPanel(new GridLayout(1, 2)); - tempPanel.add(new JLabel("Height (m)")); - virtualHeightField = new JFormattedTextField(doubleFormat); - virtualHeightField.setValue(new Double(100.0)); - tempPanel.add(virtualHeightField); - add(tempPanel); - - add(Box.createVerticalGlue()); - add(Box.createVerticalStrut(10)); - - tempPanel = new JPanel(); - tempPanel.setLayout(new BoxLayout(tempPanel, BoxLayout.X_AXIS)); - tempPanel.add(Box.createHorizontalGlue()); - - final JButton okButton = new JButton("OK"); - this.getRootPane().setDefaultButton(okButton); - final JButton cancelButton = new JButton("Cancel"); - okButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - virtualStartX = ((Number) virtualStartXField.getValue()).doubleValue(); - virtualStartY = ((Number) virtualStartYField.getValue()).doubleValue(); - virtualWidth = ((Number) virtualWidthField.getValue()).doubleValue(); - virtualHeight = ((Number) virtualHeightField.getValue()).doubleValue(); - - terminatedOK = true; - dispose(); -} - }); - cancelButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - terminatedOK = false; - dispose(); - } - }); - - tempPanel.add(okButton); - tempPanel.add(cancelButton); - add(tempPanel); - - // Show dialog - setModal(true); - pack(); - setLocationRelativeTo(owner); - setVisible(true); - } - - public boolean terminatedOK() { - return terminatedOK; - } - public double getVirtualStartX() { - return virtualStartX; - } - public double getVirtualStartY() { - return virtualStartY; - } - public double getVirtualWidth() { - return virtualWidth; - } - public double getVirtualHeight() { - return virtualHeight; - } - - } - - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("set background image")) { - - // Let user select image file - JFileChooser fileChooser = new JFileChooser(); - ImageFilter filter = new ImageFilter(); - fileChooser.addChoosableFileFilter(filter); - - int returnVal = fileChooser.showOpenDialog(canvas); - - if (returnVal != JFileChooser.APPROVE_OPTION) { - // User cancelled - return; - } - - File file = fileChooser.getSelectedFile(); - - // User selected non-supported file, aborting - if (!filter.accept(file)) { - logger.fatal("Non-supported file type, aborting"); - return; - } - - logger.info("Opening: " + file.getName() + "."); - - // Load image using toolkit and media tracker - Toolkit toolkit = Toolkit.getDefaultToolkit(); - Image image = toolkit.getImage(file.getAbsolutePath()); - - MediaTracker tracker = new MediaTracker(canvas); - tracker.addImage(image, 1); - - try { - tracker.waitForAll(); - if (tracker.isErrorAny()) { - logger.fatal("Error when loading image: "); - for (Object errorObject: tracker.getErrorsAny()) - logger.fatal("> " + errorObject); - } - if (image == null) { - logger.fatal("Image is null, aborting"); - return; - } - } catch (InterruptedException ex) { - logger.fatal("Interrupted during image loading, aborting"); - return; - } - - // Let user set virtual size of loaded image - ImageSettingsDialog dialog = new ImageSettingsDialog(file, image, GUI.frame); - - if (!dialog.terminatedOK()) { - logger.fatal("User cancelled, aborting"); - return; - } - - // Add background image - backgroundStartX = dialog.getVirtualStartX(); - backgroundStartY = dialog.getVirtualStartY(); - backgroundWidth = dialog.getVirtualWidth(); - backgroundHeight = dialog.getVirtualHeight(); - - backgroundImage = image; - backgroundImageFile = file; - } - } - }; - - /** - * Helps user analyze a background for obstacles. - */ - private ActionListener analyzeObstaclesHandler = new ActionListener() { - - class AnalyzeImageDialog extends JDialog { - - private NumberFormat intFormat = NumberFormat.getIntegerInstance(); - private BufferedImage imageToAnalyze = null; - private BufferedImage obstacleImage = null; - private JPanel canvasPanel = null; - private boolean[][] obstacleArray = null; - private boolean exitedOK = false; - - private JSlider redSlider, greenSlider, blueSlider, toleranceSlider, sizeSlider; - - /** - * Listens to preview mouse motion event (when picking color) - */ - private MouseMotionListener myMouseMotionListener = new MouseMotionListener() { - public void mouseDragged(MouseEvent e) { - - } - public void mouseMoved(MouseEvent e) { - // Convert from mouse to image pixel position - Point pixelPoint = new Point( - (int) (e.getX() * (((double) imageToAnalyze.getWidth()) / ((double) canvasPanel.getWidth()))), - (int) (e.getY() * (((double) imageToAnalyze.getHeight()) / ((double) canvasPanel.getHeight()))) - ); - - // Fetch color - int color = imageToAnalyze.getRGB(pixelPoint.x, pixelPoint.y); - int red = (color & 0x00ff0000) >> 16; - int green = (color & 0x0000ff00) >> 8; - int blue = color & 0x000000ff; - - // Update sliders - redSlider.setValue(red); - redSlider.repaint(); - greenSlider.setValue(green); - greenSlider.repaint(); - blueSlider.setValue(blue); - blueSlider.repaint(); - } - }; - - /** - * Listens to preview mouse event (when picking color) - */ - private MouseListener myMouseListener = new MouseListener() { - public void mouseClicked(MouseEvent e) { - - } - public void mouseReleased(MouseEvent e) { - - } - public void mouseEntered(MouseEvent e) { - - } - public void mouseExited(MouseEvent e) { - - } - public void mousePressed(MouseEvent e) { - // Stop picking color again; remove mouse listeners and reset mouse cursor - MouseListener[] allMouseListeners = canvasPanel.getMouseListeners(); - for (MouseListener mouseListener: allMouseListeners) - canvasPanel.removeMouseListener(mouseListener); - - MouseMotionListener[] allMouseMotionListeners = canvasPanel.getMouseMotionListeners(); - for (MouseMotionListener mouseMotionListener: allMouseMotionListeners) - canvasPanel.removeMouseMotionListener(mouseMotionListener); - - canvasPanel.setCursor(Cursor.getDefaultCursor()); - } - }; - - /** - * Creates a new dialog for settings background parameters - */ - protected AnalyzeImageDialog(Image currentImage, ChannelModel currentChannelModel, Frame owner) { - super(owner, "Analyze for obstacles"); - - JPanel tempPanel; - JLabel tempLabel; - JSlider tempSlider; - JButton tempButton; - - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - Dimension labelDimension = new Dimension(100, 20); - - // Convert Image to BufferedImage - imageToAnalyze = new BufferedImage( - currentImage.getWidth(this), - currentImage.getHeight(this), - BufferedImage.TYPE_INT_ARGB - ); - Graphics2D g = imageToAnalyze.createGraphics(); - g.drawImage(currentImage, 0, 0, null); - - // Prepare initial obstacle image - obstacleImage = new BufferedImage( - currentImage.getWidth(this), - currentImage.getHeight(this), - BufferedImage.TYPE_INT_ARGB - ); - - // Set layout and add components - intFormat.setMinimumIntegerDigits(1); - intFormat.setMaximumIntegerDigits(3); - intFormat.setParseIntegerOnly(true); - setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS)); - - // Obstacle color - tempPanel = new JPanel(); - tempPanel.setLayout(new BoxLayout(tempPanel, BoxLayout.X_AXIS)); - tempPanel.add(tempLabel = new JLabel("Obstacle")); - tempLabel.setPreferredSize(labelDimension); - add(tempPanel); - - tempPanel = new JPanel(); - tempPanel.setLayout(new BoxLayout(tempPanel, BoxLayout.X_AXIS)); - tempPanel.add(tempLabel = new JLabel("Red")); - tempLabel.setPreferredSize(labelDimension); - tempLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); - tempPanel.add(tempSlider = new JSlider(JSlider.HORIZONTAL, 0, 255, 0)); - tempSlider.setMajorTickSpacing(50); - tempSlider.setPaintTicks(true); - tempSlider.setPaintLabels(true); - add(tempPanel); - redSlider = tempSlider; - - tempPanel = new JPanel(); - tempPanel.setLayout(new BoxLayout(tempPanel, BoxLayout.X_AXIS)); - tempPanel.add(tempLabel = new JLabel("Green")); - tempLabel.setPreferredSize(labelDimension); - tempLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); - tempPanel.add(tempSlider = new JSlider(JSlider.HORIZONTAL, 0, 255, 0)); - tempSlider.setMajorTickSpacing(50); - tempSlider.setPaintTicks(true); - tempSlider.setPaintLabels(true); - add(tempPanel); - greenSlider = tempSlider; - - tempPanel = new JPanel(); - tempPanel.setLayout(new BoxLayout(tempPanel, BoxLayout.X_AXIS)); - tempPanel.add(tempLabel = new JLabel("Blue")); - tempLabel.setPreferredSize(labelDimension); - tempLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); - tempPanel.add(tempSlider = new JSlider(JSlider.HORIZONTAL, 0, 255, 0)); - tempSlider.setMajorTickSpacing(50); - tempSlider.setPaintTicks(true); - tempSlider.setPaintLabels(true); - add(tempPanel); - blueSlider = tempSlider; - - // Tolerance - tempPanel = new JPanel(); - tempPanel.setLayout(new BoxLayout(tempPanel, BoxLayout.X_AXIS)); - tempPanel.add(tempLabel = new JLabel("Tolerance")); - tempLabel.setPreferredSize(labelDimension); - tempLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); - tempPanel.add(tempSlider = new JSlider(JSlider.HORIZONTAL, 0, 128, 0)); - tempSlider.setMajorTickSpacing(25); - tempSlider.setPaintTicks(true); - tempSlider.setPaintLabels(true); - add(tempPanel); - toleranceSlider = tempSlider; - - // Obstacle size - tempPanel = new JPanel(); - tempPanel.setLayout(new BoxLayout(tempPanel, BoxLayout.X_AXIS)); - tempPanel.add(tempLabel = new JLabel("Obstacle size")); - tempLabel.setPreferredSize(labelDimension); - tempLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); - tempPanel.add(tempSlider = new JSlider(JSlider.HORIZONTAL, 1, 40, 40)); - tempSlider.setInverted(true); - tempSlider.setMajorTickSpacing(5); - tempSlider.setPaintTicks(true); - tempSlider.setPaintLabels(true); - add(tempPanel); - sizeSlider = tempSlider; - - // Buttons: Pick color, Preview obstacles etc. - tempPanel = new JPanel(); - tempPanel.setLayout(new BoxLayout(tempPanel, BoxLayout.X_AXIS)); - tempPanel.add(Box.createHorizontalGlue()); - tempPanel.add(tempButton = new JButton("Pick color")); - tempButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - // Set to color picker mode (if not already there) - if (canvasPanel.getMouseMotionListeners().length == 0) { - canvasPanel.addMouseListener(myMouseListener); - canvasPanel.addMouseMotionListener(myMouseMotionListener); - canvasPanel.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); - } - } - }); - tempPanel.add(Box.createHorizontalStrut(5)); - tempPanel.add(tempButton = new JButton("Preview obstacles")); - tempButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - obstacleImage = createObstacleImage(); - canvasPanel.repaint(); - } - }); - add(tempPanel); - - add(Box.createVerticalStrut(10)); - - // Preview image - tempPanel = new JPanel() { - public void paintComponent(Graphics g) { - super.paintComponent(g); - g.drawImage(imageToAnalyze, 0, 0, getWidth(), getHeight(), this); - g.drawImage(obstacleImage, 0, 0, getWidth(), getHeight(), this); - } - }; - tempPanel.setBorder( - BorderFactory.createTitledBorder( - BorderFactory.createLineBorder(Color.BLACK), "Preview")); - tempPanel.setPreferredSize(new Dimension(400, 400)); - tempPanel.setBackground(Color.CYAN); - add(tempPanel); - canvasPanel = tempPanel; // Saved in canvasPanel - - // Buttons: Cancel, OK - tempPanel = new JPanel(); - tempPanel.setLayout(new BoxLayout(tempPanel, BoxLayout.X_AXIS)); - tempPanel.add(Box.createHorizontalGlue()); - tempPanel.add(tempButton = new JButton("Cancel")); - tempButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - dispose(); - } - }); - tempPanel.add(Box.createHorizontalStrut(5)); - tempPanel.add(tempButton = new JButton("OK")); - tempButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - obstacleImage = createObstacleImage(); - exitedOK = true; - dispose(); - } - }); - add(tempPanel); - - - add(Box.createVerticalGlue()); - add(Box.createVerticalStrut(10)); - - // Show dialog - setModal(true); - pack(); - setLocationRelativeTo(owner); - setVisible(true); - } - - /** - * Create obstacle image by analyzing current background image - * and using the current obstacle color, size and tolerance. - * This method also creates the boolean array obstacleArray. - * - * @return New obstacle image - */ - private BufferedImage createObstacleImage() { - int nrObstacles = 0; - - // Create new obstacle image all transparent (no obstacles) - BufferedImage newObstacleImage = new BufferedImage( - imageToAnalyze.getWidth(), - imageToAnalyze.getHeight(), - BufferedImage.TYPE_INT_ARGB - ); - for (int x=0; x < imageToAnalyze.getWidth(); x++) { - for (int y=0; y < imageToAnalyze.getHeight(); y++) { - newObstacleImage.setRGB(x, y, 0x00000000); - } - } - - // Get target color to match against - int targetRed = redSlider.getValue(); - int targetGreen = greenSlider.getValue(); - int targetBlue = blueSlider.getValue(); - - // Get obstacle resolution and size - int boxSize = sizeSlider.getValue(); - int tolerance = toleranceSlider.getValue(); - - // Divide image into boxes and check each box for obstacles - int arrayWidth = (int) Math.ceil((double) imageToAnalyze.getWidth() / (double) boxSize); - int arrayHeight = (int) Math.ceil((double) imageToAnalyze.getHeight() / (double) boxSize); - - obstacleArray = new boolean[arrayWidth][arrayHeight]; - for (int x=0; x < imageToAnalyze.getWidth(); x+=boxSize) { - for (int y=0; y < imageToAnalyze.getHeight(); y+=boxSize) { - boolean boxIsObstacle = false; - - // Check all pixels in box for obstacles - for (int xx=x; xx < x + boxSize && xx < imageToAnalyze.getWidth(); xx++) { - for (int yy=y; yy < y + boxSize && yy < imageToAnalyze.getHeight(); yy++) { - - // Get current pixel color - int color = imageToAnalyze.getRGB(xx, yy); - int red = (color & 0x00ff0000) >> 16; - int green = (color & 0x0000ff00) >> 8; - int blue = color & 0x000000ff; - - // Calculate difference from target color - int difference = - Math.abs(red - targetRed) + - Math.abs(green - targetGreen) + - Math.abs(blue - targetBlue); - - // If difference is small enough make this box an obstacle - if (difference <= tolerance) { - boxIsObstacle = true; - break; - } - } - if (boxIsObstacle) - break; - } - - // If box is obstacle, colorize it - if (boxIsObstacle) { - obstacleArray[x/boxSize][y/boxSize] = true; - nrObstacles++; - - // Colorize all pixels in the box - for (int xx=x; xx < x + boxSize && xx < imageToAnalyze.getWidth(); xx++) { - for (int yy=y; yy < y + boxSize && yy < imageToAnalyze.getHeight(); yy++) { - newObstacleImage.setRGB(xx, yy, 0x9922ff22); - } - } - } else - obstacleArray[x/boxSize][y/boxSize] = false; - - - } - } // End of "divide into boxes" for-loop - - return newObstacleImage; - } - - } - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("analyze for obstacles")) { - if (backgroundImage == null) - return; - - AnalyzeImageDialog analyzer = new AnalyzeImageDialog( - backgroundImage, - currentChannelModel, - GUI.frame - ); - - // Check return value from analyzer - if (analyzer.exitedOK) { - // Remove old obstacle and register new - final boolean[][] obstacleArray = analyzer.obstacleArray; - - final int boxSize = analyzer.sizeSlider.getValue(); - - // Create progress monitor - final ProgressMonitor pm = new ProgressMonitor( - GUI.frame, - "Registering obstacles", - null, - 0, - obstacleArray.length - 1 - ); - - // Thread that will perform the work - final Runnable runnable = new Runnable() { - public void run() { - try { - int foundObstacles = 0; - - // Clear all old obstacles - currentChannelModel.removeAllObstacles(); - - for (int x=0; x < obstacleArray.length; x++) { - for (int y=0; y < (obstacleArray[0]).length; y++) { - // If obstacle, register it - if (obstacleArray[x][y]) { - double realWidth = ((double) boxSize * backgroundWidth) / (double) backgroundImage.getWidth(null); - double realHeight = ((double) boxSize * backgroundHeight) / (double) backgroundImage.getHeight(null); - double realStartX = backgroundStartX + (double) x * realWidth; - double realStartY = backgroundStartY + (double) y * realHeight; - - foundObstacles++; - - if (realStartX + realWidth > backgroundStartX + backgroundWidth) - realWidth = backgroundStartX + backgroundWidth - realStartX; - if (realStartY + realHeight > backgroundStartY + backgroundHeight) - realHeight = backgroundStartY + backgroundHeight - realStartY; - - currentChannelModel.addRectObstacle( - realStartX, - realStartY, - realWidth, - realHeight, - false - ); - } - } - // Check if the dialog has been cancelled - if (pm.isCanceled()) return; - - // Update progress - pm.setProgress(x); - pm.setNote("After/Before merging: " + - currentChannelModel.getNumberOfObstacles() + - "/" + - foundObstacles); - } - currentChannelModel.notifySettingsChanged(); - - thisPlugin.repaint(); - - } catch (Exception ex) { - if (pm.isCanceled()) return; - logger.fatal("Obstacle adding aborted..: "); - ex.printStackTrace(); - pm.close(); - } - pm.close(); - } - }; - - // Start thread - Thread thread = new Thread(runnable); - thread.start(); - } - } - } - }; - - /** - * Listens to settings changes in the radio medium. - */ - private Observer radioMediumSettingsObserver = new Observer() { - public void update(Observable obs, Object obj) { - // Clear selected radio (if any selected) and radio medium coverage - selectedRadio = null; - channelImage = null; - canvas.repaint(); - } - }; - - /** - * Listens to settings changes in the radio medium. - */ - private Observer radioMediumActivityObserver = new Observer() { - public void update(Observable obs, Object obj) { - // Just remove any selected radio (it may have been removed) - canvas.repaint(); - } - }; - - /** - * Listens to settings changes in the channel model. - */ - private Observer channelModelSettingsObserver = new Observer() { - public void update(Observable obs, Object obj) { - needToRepaintObstacleImage = true; - canvas.repaint(); - } - }; - - /** - * Returns a color corresponding to given value where higher values are more green, and lower values are more red. - * - * @param value Signal strength of received signal (dB) - * @param lowBorder - * @param highBorder - * @return Integer containing standard ARGB color. - */ - private int getColorOfSignalStrength(double value, double lowBorder, double highBorder) { - double upperLimit = highBorder; // Best signal adds green - double lowerLimit = lowBorder; // Bad signal adds red - double intervalSize = (upperLimit - lowerLimit) / 2; - double middleValue = lowerLimit + (upperLimit - lowerLimit) / 2; - - if (value > highBorder) { - return 0xCC00FF00; - } - - if (value < lowerLimit) { - return 0xCCFF0000; - } - - int red = 0, green = 0, blue = 0, alpha = 0xCC; - - // Upper limit (green) - if (value > upperLimit - intervalSize) { - green = (int) (255 - 255*(upperLimit - value)/intervalSize); - } - - // Medium signal adds blue - if (value > middleValue - intervalSize && value < middleValue + intervalSize) { - blue = (int) (255 - 255*Math.abs(middleValue - value)/intervalSize); - } - - // Bad signal adds red - if (value < lowerLimit + intervalSize) { - red = (int) (255 - 255*(value - lowerLimit)/intervalSize); - } - - return (alpha << 24) | (red << 16) | (green << 8) | blue; - } - - /** - * Helps user adjust and calculate the channel propagation formula - */ - private ActionListener formulaHandler = new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("recalculate visible area")) { - - // Get resolution of new image - final Dimension resolution = new Dimension( - resolutionSlider.getValue(), - resolutionSlider.getValue() - ); - - // Abort if no radio selected - if (selectedRadio == null) { - channelImage = null; - canvas.repaint(); - return; - } - - // Get new location/size of area to attenuate - final double startX = -currentPanX; - final double startY = -currentPanY; - final double width = canvas.getWidth() / currentZoomX; - final double height = canvas.getHeight() / currentZoomY; - - // Get sending radio position - Position radioPosition = currentRadioMedium.getRadioPosition(selectedRadio); - final double radioX = radioPosition.getXCoordinate(); - final double radioY = radioPosition.getYCoordinate(); - - // Create temporary image - final BufferedImage tempChannelImage = new BufferedImage(resolution.width, resolution.height, BufferedImage.TYPE_INT_ARGB); - - // Save time for later analysis - final long timeBeforeCalculating = System.currentTimeMillis(); - - // Create progress monitor - final ProgressMonitor pm = new ProgressMonitor( - GUI.frame, - "Calculating channel attenuation", - null, - 0, - resolution.width - 1 - ); - - // Thread that will perform the work - final Runnable runnable = new Runnable() { - public void run() { - try { - - // Available signal strength intervals - double lowestImageValue = Double.MAX_VALUE; - double highestImageValue = -Double.MAX_VALUE; - - // Create image values (calculate each pixel) - double[][] imageValues = new double[resolution.width][resolution.height]; - for (int x=0; x < resolution.width; x++) { - for (int y=0; y < resolution.height; y++) { - - if (dataTypeToVisualize == ChannelModel.TransmissionData.SIGNAL_STRENGTH) { - // Attenuate - double[] signalStrength = currentChannelModel.getReceivedSignalStrength( - radioX, - radioY, - startX + width * x/(double) resolution.width, - startY + height * y/(double) resolution.height - ); - - // Collecting signal strengths - if (signalStrength[0] < lowestImageValue) - lowestImageValue = signalStrength[0]; - if (signalStrength[0] > highestImageValue) - highestImageValue = signalStrength[0]; - - imageValues[x][y] = signalStrength[0]; - - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.SIGNAL_STRENGTH_VAR) { - // Attenuate - double[] signalStrength = currentChannelModel.getReceivedSignalStrength( - radioX, - radioY, - startX + width * x/(double) resolution.width, - startY + height * y/(double) resolution.height - ); - - // Collecting variances - if (signalStrength[1] < lowestImageValue) - lowestImageValue = signalStrength[1]; - if (signalStrength[1] > highestImageValue) - highestImageValue = signalStrength[1]; - - imageValues[x][y] = signalStrength[1]; - - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.SNR) { - // Get signal to noise ratio - double[] snr = currentChannelModel.getSINR( - radioX, - radioY, - startX + width * x/(double) resolution.width, - startY + height * y/(double) resolution.height, - -Double.MAX_VALUE - ); - - // Collecting signal to noise ratio - if (snr[0] < lowestImageValue) - lowestImageValue = snr[0]; - if (snr[0] > highestImageValue) - highestImageValue = snr[0]; - - imageValues[x][y] = snr[0]; - - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.SNR_VAR) { - // Get signal to noise ratio - double[] snr = currentChannelModel.getSINR( - radioX, - radioY, - startX + width * x/(double) resolution.width, - startY + height * y/(double) resolution.height, - -Double.MAX_VALUE - ); - - // Collecting variances - if (snr[1] < lowestImageValue) - lowestImageValue = snr[1]; - if (snr[1] > highestImageValue) - highestImageValue = snr[1]; - - imageValues[x][y] = snr[1]; - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.PROB_OF_RECEPTION) { - // Get probability of receiving a packet TODO What size? Does it matter? - double probability = currentChannelModel.getProbability( - radioX, - radioY, - startX + width * x/(double) resolution.width, - startY + height * y/(double) resolution.height, - -Double.MAX_VALUE - )[0]; - - // Collecting variances - if (probability < lowestImageValue) - lowestImageValue = probability; - if (probability > highestImageValue) - highestImageValue = probability; - - imageValues[x][y] = probability; - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.DELAY_SPREAD_RMS) { - // Get RMS delay spread of receiving a packet - double rmsDelaySpread = currentChannelModel.getRMSDelaySpread( - radioX, - radioY, - startX + width * x/(double) resolution.width, - startY + height * y/(double) resolution.height - ); - - // Collecting variances - if (rmsDelaySpread < lowestImageValue) - lowestImageValue = rmsDelaySpread; - if (rmsDelaySpread > highestImageValue) - highestImageValue = rmsDelaySpread; - - imageValues[x][y] = rmsDelaySpread; - } - - // Check if the dialog has been cancelled - if (pm.isCanceled()) return; - - // Update progress - pm.setProgress(x); - - } - } - - // Adjust coloring signal strength limit - if (coloringIsFixed) { - if (dataTypeToVisualize == ChannelModel.TransmissionData.SIGNAL_STRENGTH) { - lowestImageValue = -100; - highestImageValue = 0; - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.SIGNAL_STRENGTH_VAR) { - lowestImageValue = 0; - highestImageValue = 20; - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.SNR) { - lowestImageValue = -10; - highestImageValue = 30; - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.SNR_VAR) { - lowestImageValue = 0; - highestImageValue = 20; - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.PROB_OF_RECEPTION) { - lowestImageValue = 0; - highestImageValue = 1; - } else if (dataTypeToVisualize == ChannelModel.TransmissionData.DELAY_SPREAD_RMS) { - lowestImageValue = 0; - highestImageValue = 5; - } - } - - // Save coloring high-low interval - coloringHighest = highestImageValue; - coloringLowest = lowestImageValue; - - // Create image - for (int x=0; x < resolution.width; x++) { - for (int y=0; y < resolution.height; y++) { - - tempChannelImage.setRGB( - x, - y, - getColorOfSignalStrength(imageValues[x][y], lowestImageValue, highestImageValue) - ); - } - } - logger.info("Attenuating area done, time=" + (System.currentTimeMillis() - timeBeforeCalculating)); - - // Repaint to show the new channel propagation - channelStartX = startX; - channelStartY = startY; - channelWidth = width; - channelHeight = height; - channelImage = tempChannelImage; - - thisPlugin.repaint(); - coloringIntervalPanel.repaint(); - - } catch (Exception ex) { - if (pm.isCanceled()) return; - logger.fatal("Attenuation aborted: " + ex); - ex.printStackTrace(); - pm.close(); - } - pm.close(); - } - }; - - // Start thread - attenuatorThread = new Thread(runnable); - attenuatorThread.start(); - } - } - }; - - /** - * Repaint the canvas - * @param g2d Current graphics to paint on - */ - protected void repaintCanvas(Graphics2D g2d) { - AffineTransform originalTransform = g2d.getTransform(); - - // Create "real-world" transformation (scaled 100 times to reduce double->int rounding errors) - g2d.scale(currentZoomX, currentZoomY); - g2d.translate(currentPanX, currentPanY); - AffineTransform realWorldTransform = g2d.getTransform(); - g2d.scale(0.01, 0.01); - AffineTransform realWorldTransformScaled = g2d.getTransform(); - - // -- Draw background image if any -- - if (drawBackgroundImage && backgroundImage != null) { - g2d.setTransform(realWorldTransformScaled); - - g2d.drawImage(backgroundImage, - (int) ((double) backgroundStartX * 100.0), - (int) ((double) backgroundStartY * 100.0), - (int) ((double) backgroundWidth * 100.0), - (int) ((double) backgroundHeight * 100.0), - this); - } - - // -- Draw calculated obstacles -- - if (drawCalculatedObstacles) { - - // (Re)create obstacle image if needed - if (obstacleImage == null || needToRepaintObstacleImage) { - - // Abort if no obstacles exist - if (currentChannelModel.getNumberOfObstacles() > 0) { - - // Get bounds of obstacles - obstacleStartX = currentChannelModel.getObstacle(0).getMinX(); - obstacleStartY = currentChannelModel.getObstacle(0).getMinY(); - obstacleWidth = currentChannelModel.getObstacle(0).getMaxX(); - obstacleHeight = currentChannelModel.getObstacle(0).getMaxY(); - - double tempVal = 0; - for (int i=0; i < currentChannelModel.getNumberOfObstacles(); i++) { - if ((tempVal = currentChannelModel.getObstacle(i).getMinX()) < obstacleStartX) - obstacleStartX = tempVal; - if ((tempVal = currentChannelModel.getObstacle(i).getMinY()) < obstacleStartY) - obstacleStartY = tempVal; - if ((tempVal = currentChannelModel.getObstacle(i).getMaxX()) > obstacleWidth) - obstacleWidth = tempVal; - if ((tempVal = currentChannelModel.getObstacle(i).getMaxY()) > obstacleHeight) - obstacleHeight = tempVal; - } - obstacleWidth -= obstacleStartX; - obstacleHeight -= obstacleStartY; - - // Create new obstacle image - BufferedImage tempObstacleImage; - if (backgroundImage != null) - tempObstacleImage = new BufferedImage( - Math.max(600, backgroundImage.getWidth(null)), - Math.max(600, backgroundImage.getHeight(null)), - BufferedImage.TYPE_INT_ARGB - ); - else - tempObstacleImage = new BufferedImage( - 600, - 600, - BufferedImage.TYPE_INT_ARGB - ); - - Graphics2D obstacleGraphics = (Graphics2D) tempObstacleImage.getGraphics(); - - // Set real world transform - obstacleGraphics.scale( - (double) tempObstacleImage.getWidth()/obstacleWidth, - (double) tempObstacleImage.getHeight()/obstacleHeight - ); - obstacleGraphics.translate(-obstacleStartX, -obstacleStartY); - - - // Paint all obstacles - obstacleGraphics.setColor(new Color(0, 0, 0, 128)); - - // DEBUG: Use random obstacle color to distinguish different obstacles - //Random random = new Random(); - - for (int i=0; i < currentChannelModel.getNumberOfObstacles(); i++) { - //obstacleGraphics.setColor((new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255), 128))); - obstacleGraphics.fill(currentChannelModel.getObstacle(i)); - } - obstacleImage = tempObstacleImage; - - } else { - - // No obstacles exist - create dummy obstacle image - obstacleStartX = 0; - obstacleStartY = 0; - obstacleWidth = 1; - obstacleHeight = 1; - obstacleImage = new BufferedImage( - 1, - 1, - BufferedImage.TYPE_INT_ARGB - ); - } - - needToRepaintObstacleImage = false; - } - - // Painting in real world coordinates - g2d.setTransform(realWorldTransformScaled); - - g2d.drawImage(obstacleImage, - (int) ((double) obstacleStartX * 100.0), - (int) ((double) obstacleStartY * 100.0), - (int) ((double) obstacleWidth * 100.0), - (int) ((double) obstacleHeight * 100.0), - this); - } - - // -- Draw channel probabilities if calculated -- - if (drawChannelProbabilities && channelImage != null) { - g2d.setTransform(realWorldTransformScaled); - - g2d.drawImage(channelImage, - (int) ((double) channelStartX * 100.0), - (int) ((double) channelStartY * 100.0), - (int) ((double) channelWidth * 100.0), - (int) ((double) channelHeight * 100.0), - this); - } - - // -- Draw radios -- - if (drawRadios) { - for (int i=0; i < currentRadioMedium.getRegisteredRadioCount(); i++) { - g2d.setStroke(new BasicStroke((float) 0.0)); - g2d.setTransform(realWorldTransform); - - // Translate to real world radio position - Radio radio = currentRadioMedium.getRegisteredRadio(i); - Position radioPosition = currentRadioMedium.getRadioPosition(radio); - g2d.translate( - radioPosition.getXCoordinate(), - radioPosition.getYCoordinate() - ); - - // Fetch current translation - double xPos = g2d.getTransform().getTranslateX(); - double yPos = g2d.getTransform().getTranslateY(); - - // Jump to identity transform and paint without scaling - g2d.setTransform(new AffineTransform()); - - if (selectedRadio == radio) { - g2d.setColor(new Color(255, 0, 0, 100)); - g2d.fillRect( - (int) xPos - antennaImage.getWidth(this)/2, - (int) yPos - antennaImage.getHeight(this)/2, - (int) antennaImage.getWidth(this), - (int) antennaImage.getHeight(this) - ); - g2d.setColor(Color.BLUE); - g2d.drawRect( - (int) xPos - antennaImage.getWidth(this)/2, - (int) yPos - antennaImage.getHeight(this)/2, - (int) antennaImage.getWidth(this), - (int) antennaImage.getHeight(this) - ); - } - - g2d.drawImage(antennaImage, (int) xPos - antennaImage.getWidth(this)/2, (int) yPos - antennaImage.getHeight(this)/2, this); - - } - } - - // -- Draw radio activity -- - if (drawRadioActivity) { - // Paint scaled (otherwise bad rounding to integers may occur) - g2d.setTransform(realWorldTransformScaled); - g2d.setStroke(new BasicStroke((float) 0.0)); - - for (RadioInterference interference: currentRadioMedium.getCurrentInterferencesArray()) { - g2d.setColor(Color.RED); - - // Get source and destination coordinates - Position sourcePosition = interference.mySource.source.position; - Position destinationPosition = interference.myDestination.position; - - g2d.draw(new Line2D.Double( - sourcePosition.getXCoordinate()*100.0, - sourcePosition.getYCoordinate()*100.0, - destinationPosition.getXCoordinate()*100.0, - destinationPosition.getYCoordinate()*100.0 - )); - } - for (RadioTransfer transfer: currentRadioMedium.getCurrentTransfersArray()) { - g2d.setColor(Color.GREEN); - - // Get source and destination coordinates - Position sourcePosition = transfer.mySource.source.position; - Position destinationPosition = transfer.myDestination.position; - - g2d.draw(new Line2D.Double( - sourcePosition.getXCoordinate()*100.0, - sourcePosition.getYCoordinate()*100.0, - destinationPosition.getXCoordinate()*100.0, - destinationPosition.getYCoordinate()*100.0 - )); - } - for (RadioTransmission transmission: currentRadioMedium.getCurrentTransmissionsArray()) { - g2d.setColor(Color.BLUE); - - g2d.setTransform(realWorldTransform); - Position sourcePosition = transmission.source.position; - - g2d.translate( - sourcePosition.getXCoordinate(), - sourcePosition.getYCoordinate() - ); - - // Fetch current translation - double xPos = g2d.getTransform().getTranslateX(); - double yPos = g2d.getTransform().getTranslateY(); - - // Jump to identity transform and paint without scaling - g2d.setTransform(new AffineTransform()); - - g2d.fillOval( - (int) xPos, - (int) yPos, - (int) 5, - (int) 5 - ); - - - } - } - - // -- Draw scale arrow -- - if (drawScaleArrow) { - g2d.setStroke(new BasicStroke((float) .0)); - - g2d.setColor(Color.BLACK); - - // Decide on scale comparator - double currentArrowDistance = 0.1; // in meters - if (currentZoomX < canvas.getWidth() / 2) - currentArrowDistance = 0.1; // 0.1m - if (currentZoomX < canvas.getWidth() / 2) - currentArrowDistance = 1; // 1m - if (10 * currentZoomX < canvas.getWidth() / 2) - currentArrowDistance = 10; // 10m - if (100 * currentZoomX < canvas.getWidth() / 2) - currentArrowDistance = 100; // 100m - if (1000 * currentZoomX < canvas.getWidth() / 2) - currentArrowDistance = 1000; // 100m - - // "Arrow" points - int pixelArrowLength = (int) (currentArrowDistance * currentZoomX); - int xPoints[] = new int[] { -pixelArrowLength, -pixelArrowLength, -pixelArrowLength, 0, 0, 0 }; - int yPoints[] = new int[] { -5, 5, 0, 0, -5, 5 }; - - // Paint arrow and text - g2d.setTransform(originalTransform); - g2d.translate(canvas.getWidth() - 120, canvas.getHeight() - 20); - g2d.drawString(currentArrowDistance + "m", -30, -10); - g2d.drawPolyline(xPoints, yPoints, xPoints.length); - } - - // -- Draw tracked components (if any) -- - if (inTrackMode && trackedComponents != null) { - g2d.setTransform(realWorldTransformScaled); - g2d.setStroke(new BasicStroke((float) 0.0)); - - Random random = new Random(); - for (int i=0; i < trackedComponents.size(); i++) { - g2d.setColor(new Color(255, random.nextInt(255), random.nextInt(255), 255)); - Line2D originalLine = trackedComponents.get(i); - Line2D newLine = new Line2D.Double( - originalLine.getX1()*100.0, - originalLine.getY1()*100.0, - originalLine.getX2()*100.0, - originalLine.getY2()*100.0 - ); - - g2d.draw(newLine); - } - } - - g2d.setTransform(originalTransform); - } - - /** - * Tracks an on-screen position and returns all hit radios. - * May for example be used by a mouse listener to determine - * if user clicked on a radio. - * - * @param clickedPoint On-screen position - * @return All hit radios - */ - protected Vector trackClickedRadio(Point clickedPoint) { - Vector hitRadios = new Vector(); - if (currentRadioMedium.getRegisteredRadioCount() == 0) - return null; - - double realIconHalfWidth = antennaImage.getWidth(this) / (currentZoomX*2.0); - double realIconHalfHeight = antennaImage.getHeight(this) / (currentZoomY*2.0); - double realClickedX = clickedPoint.x / currentZoomX - currentPanX; - double realClickedY = clickedPoint.y / currentZoomY - currentPanY; - - for (int i=0; i < currentRadioMedium.getRegisteredRadioCount(); i++) { - Radio testRadio = currentRadioMedium.getRegisteredRadio(i); - Position testPosition = currentRadioMedium.getRadioPosition(testRadio); - - if (realClickedX > testPosition.getXCoordinate() - realIconHalfWidth && - realClickedX < testPosition.getXCoordinate() + realIconHalfWidth && - realClickedY > testPosition.getYCoordinate() - realIconHalfHeight && - realClickedY < testPosition.getYCoordinate() + realIconHalfHeight) { - hitRadios.add(testRadio); - } - } - - if (hitRadios.size() == 0) - return null; - return hitRadios; - } - - public void closePlugin() { - // Remove all our observers - - if (currentChannelModel != null && channelModelSettingsObserver != null) { - currentChannelModel.deleteSettingsObserver(channelModelSettingsObserver); - } else { - logger.fatal("Could not remove observer: " + channelModelSettingsObserver); - } - - if (currentRadioMedium != null && radioMediumSettingsObserver != null) { - currentRadioMedium.deleteSettingsObserver(radioMediumSettingsObserver); - } else { - logger.fatal("Could not remove observer: " + radioMediumSettingsObserver); - } - - if (currentRadioMedium != null && radioMediumActivityObserver != null) { - currentRadioMedium.deleteRadioMediumObserver(radioMediumActivityObserver); - } else { - logger.fatal("Could not remove observer: " + radioMediumActivityObserver); - } - } - - - /** - * Returns XML elements representing the current configuration. - * - * @see #setConfigXML(Collection) - * @return XML element collection - */ - public Collection getConfigXML() { - Vector config = new Vector(); - Element element; - - // Controls visible - element = new Element("controls_visible"); - element.setText(Boolean.toString(showSettingsBox.isSelected())); - config.add(element); - - // Viewport - element = new Element("zoom_x"); - element.setText(Double.toString(currentZoomX)); - config.add(element); - element = new Element("zoom_y"); - element.setText(Double.toString(currentZoomY)); - config.add(element); - element = new Element("pan_x"); - element.setText(Double.toString(currentPanX)); - config.add(element); - element = new Element("pan_y"); - element.setText(Double.toString(currentPanY)); - config.add(element); - - // Components shown - element = new Element("show_background"); - element.setText(Boolean.toString(drawBackgroundImage)); - config.add(element); - element = new Element("show_obstacles"); - element.setText(Boolean.toString(drawCalculatedObstacles)); - config.add(element); - element = new Element("show_channel"); - element.setText(Boolean.toString(drawChannelProbabilities)); - config.add(element); - element = new Element("show_radios"); - element.setText(Boolean.toString(drawRadios)); - config.add(element); - element = new Element("show_activity"); - element.setText(Boolean.toString(drawRadioActivity)); - config.add(element); - element = new Element("show_arrow"); - element.setText(Boolean.toString(drawScaleArrow)); - config.add(element); - - // Visualization type - element = new Element("vis_type"); - element.setText(visTypeSelectionGroup.getSelection().getActionCommand()); - config.add(element); - - // Background image - if (backgroundImageFile != null) { - element = new Element("background_image"); - element.setText(backgroundImageFile.getPath()); - config.add(element); - - element = new Element("back_start_x"); - element.setText(Double.toString(backgroundStartX)); - config.add(element); - element = new Element("back_start_y"); - element.setText(Double.toString(backgroundStartY)); - config.add(element); - element = new Element("back_width"); - element.setText(Double.toString(backgroundWidth)); - config.add(element); - element = new Element("back_height"); - element.setText(Double.toString(backgroundHeight)); - config.add(element); - } - - // Resolution - element = new Element("resolution"); - element.setText(Integer.toString(resolutionSlider.getValue())); - config.add(element); - - return config; - } - - /** - * Sets the configuration depending on the given XML elements. - * - * @see #getConfigXML() - * @param configXML - * Config XML elements - * @return True if config was set successfully, false otherwise - */ - public boolean setConfigXML(Collection configXML) { - for (Element element : configXML) { - if (element.getName().equals("controls_visible")) { - showSettingsBox.setSelected(Boolean.parseBoolean(element.getText())); - canvasModeHandler.actionPerformed(new ActionEvent(showSettingsBox, - ActionEvent.ACTION_PERFORMED, showSettingsBox.getActionCommand())); - } else if (element.getName().equals("zoom_x")) { - currentZoomX = Double.parseDouble(element.getText()); - } else if (element.getName().equals("zoom_y")) { - currentZoomY = Double.parseDouble(element.getText()); - } else if (element.getName().equals("pan_x")) { - currentPanX = Double.parseDouble(element.getText()); - } else if (element.getName().equals("pan_y")) { - currentPanY = Double.parseDouble(element.getText()); - } else if (element.getName().equals("show_background")) { - backgroundCheckBox.setSelected(Boolean.parseBoolean(element.getText())); - selectGraphicsHandler.actionPerformed(new ActionEvent(backgroundCheckBox, - ActionEvent.ACTION_PERFORMED, backgroundCheckBox.getActionCommand())); - } else if (element.getName().equals("show_obstacles")) { - obstaclesCheckBox.setSelected(Boolean.parseBoolean(element.getText())); - selectGraphicsHandler.actionPerformed(new ActionEvent(obstaclesCheckBox, - ActionEvent.ACTION_PERFORMED, obstaclesCheckBox.getActionCommand())); - } else if (element.getName().equals("show_channel")) { - channelCheckBox.setSelected(Boolean.parseBoolean(element.getText())); - selectGraphicsHandler.actionPerformed(new ActionEvent(channelCheckBox, - ActionEvent.ACTION_PERFORMED, channelCheckBox.getActionCommand())); - } else if (element.getName().equals("show_radios")) { - radiosCheckBox.setSelected(Boolean.parseBoolean(element.getText())); - selectGraphicsHandler.actionPerformed(new ActionEvent(radiosCheckBox, - ActionEvent.ACTION_PERFORMED, radiosCheckBox.getActionCommand())); - } else if (element.getName().equals("show_activity")) { - radioActivityCheckBox.setSelected(Boolean.parseBoolean(element.getText())); - selectGraphicsHandler.actionPerformed(new ActionEvent(radioActivityCheckBox, - ActionEvent.ACTION_PERFORMED, radioActivityCheckBox.getActionCommand())); - } else if (element.getName().equals("show_arrow")) { - arrowCheckBox.setSelected(Boolean.parseBoolean(element.getText())); - selectGraphicsHandler.actionPerformed(new ActionEvent(arrowCheckBox, - ActionEvent.ACTION_PERFORMED, arrowCheckBox.getActionCommand())); - } else if (element.getName().equals("vis_type")) { - String visTypeIdentifier = element.getText(); - Enumeration buttonEnum = visTypeSelectionGroup.getElements(); - while (buttonEnum.hasMoreElements()) { - AbstractButton button = buttonEnum.nextElement(); - if (button.getActionCommand().equals(visTypeIdentifier)) { - visTypeSelectionGroup.setSelected(button.getModel(), true); - button.getActionListeners()[0] - .actionPerformed(new ActionEvent(button, - ActionEvent.ACTION_PERFORMED, button.getActionCommand())); - } - } - } else if (element.getName().equals("background_image")) { - backgroundImageFile = new File(element.getText()); - if (backgroundImageFile.exists()) { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - backgroundImage = toolkit.getImage(backgroundImageFile.getAbsolutePath()); - - MediaTracker tracker = new MediaTracker(canvas); - tracker.addImage(backgroundImage, 1); - - try { - tracker.waitForAll(); - } catch (InterruptedException ex) { - logger.fatal("Interrupted during image loading, aborting"); - backgroundImage = null; - } - - } - } else if (element.getName().equals("back_start_x")) { - backgroundStartX = Double.parseDouble(element.getText()); - } else if (element.getName().equals("back_start_y")) { - backgroundStartY = Double.parseDouble(element.getText()); - } else if (element.getName().equals("back_width")) { - backgroundWidth = Double.parseDouble(element.getText()); - } else if (element.getName().equals("back_height")) { - backgroundHeight = Double.parseDouble(element.getText()); - } else if (element.getName().equals("resolution")) { - resolutionSlider.setValue(Integer.parseInt(element.getText())); - } else { - logger.fatal("Unknown configuration value: " + element.getName()); - } - } - - canvas.repaint(); - return true; - } - - -} diff --git a/tools/cooja/apps/arm/java/se/sics/arm/ChannelModel.java b/tools/cooja/apps/arm/java/se/sics/arm/ChannelModel.java deleted file mode 100644 index 56332bb3f..000000000 --- a/tools/cooja/apps/arm/java/se/sics/arm/ChannelModel.java +++ /dev/null @@ -1,1693 +0,0 @@ -package se.sics.arm; - -import java.awt.geom.*; -import java.util.*; -import javax.swing.tree.DefaultMutableTreeNode; -import org.apache.log4j.Logger; -import org.jdom.Element; - -import statistics.GaussianWrapper; - - -/** - * The channel model object in ARM is responsible for calulating propagation - * impact on packets being sent in the radio medium. - * - * By registering as a settings observer on this channel model, other parts will - * be notified if the settings change. - * - * TODO Add better support for different signal strengths - * - * @author Fredrik Osterlind - */ -public class ChannelModel { - private static Logger logger = Logger.getLogger(ChannelModel.class); - - enum TransmissionData { SIGNAL_STRENGTH, SIGNAL_STRENGTH_VAR, SNR, SNR_VAR, PROB_OF_RECEPTION, DELAY_SPREAD, DELAY_SPREAD_RMS} - - private Properties parameters = new Properties(); - private Properties parameterDescriptions = new Properties(); - - // Parameters used for speeding up calculations - private boolean needToPrecalculateFSPL = true; - private static double paramFSPL = 0; - private boolean needToPrecalculateOutputPower = true; - private static double paramOutputPower = 0; - - private ObstacleWorld myObstacleWorld = new ObstacleWorld(); - - // Ray tracing components temporary vector - private boolean inLoggingMode = false; - private Vector savedRays = null; - private Vector> calculatedVisibleSides = new Vector>(); - private Vector calculatedVisibleSidesSources = new Vector(); - private Vector calculatedVisibleSidesLines = new Vector(); - private Vector calculatedVisibleSidesAngleIntervals = new Vector(); - private static int maxSavedVisibleSides = 30; // Max size of lists above - - /** - * Notifies observers when this channel model has changed settings. - */ - private class SettingsObservable extends Observable { - private void notifySettingsChanged() { - setChanged(); - notifyObservers(); - } - } - private SettingsObservable settingsObservable = new SettingsObservable(); - - // A random number generator - private Random random = new Random(); - - public ChannelModel() { - // - Set initial parameter values - - - // Using random variables - parameters.put("apply_random", new Boolean(false)); // TODO Should not use random variables as default - parameterDescriptions.put("apply_random", "Apply random values immediately"); - - // Signal to noise reception threshold - parameters.put("snr_threshold", new Double(6)); - parameterDescriptions.put("snr_threshold", "SNR reception threshold (dB)"); - - // Background noise mean - parameters.put("bg_noise_mean", new Double(-150)); - parameterDescriptions.put("bg_noise_mean", "Background noise mean (dBm)"); - - // Background noise variance - parameters.put("bg_noise_var", new Double(1)); - parameterDescriptions.put("bg_noise_var", "Background noise variance (dB)"); - - // Extra system gain mean - parameters.put("system_gain_mean", new Double(0)); - parameterDescriptions.put("system_gain_mean", "Extra system gain mean (dB)"); - - // Extra system gain variance - parameters.put("system_gain_var", new Double(4)); // TODO Should probably be default 0 or 1 - parameterDescriptions.put("system_gain_var", "Extra system gain variance (dB)"); - - // Transmission wavelength - parameters.put("wavelength", new Double(0.346)); // ~868 MHz (RFM TR1001) - parameterDescriptions.put("wavelength", "Wavelength w (m)"); - - // Transmitter output power - parameters.put("tx_power", new Double(1.5)); // dBm (deciBel milliwatts) - parameterDescriptions.put("tx_power", "Transmitter output power (dBm)"); - - // Transmitter antenna gain - parameters.put("tx_antenna_gain", new Double(0)); // TODO Should use angle - parameterDescriptions.put("tx_antenna_gain", "Transmitter antenna gain (dB)"); - - // Receiver sensitivity - parameters.put("rx_sensitivity", new Double(-100)); - parameterDescriptions.put("rx_sensitivity", "Receiver sensitivity (dBm)"); - - // Receiver antenna gain - parameters.put("rx_antenna_gain", new Double(0)); // TODO Should use angle - parameterDescriptions.put("rx_antenna_gain", "Receiver antenna gain (dB)"); - - // Ray Tracer - Disallow direct path - parameters.put("rt_disallow_direct_path", new Boolean(false)); - parameterDescriptions.put("rt_disallow_direct_path", "Disallow direct path"); - - // Ray Tracer - If direct path exists, ignore the non-direct (used for debugging) - parameters.put("rt_ignore_non_direct", new Boolean(false)); - parameterDescriptions.put("rt_ignore_non_direct", "If existing, only use direct path"); - - // Ray Tracer - Use FSPL on total length only - parameters.put("rt_fspl_on_total_length", new Boolean(true)); - parameterDescriptions.put("rt_fspl_on_total_length", "Use FSPL on total path lengths only"); - - // Ray Tracer - Max number of subrays - parameters.put("rt_max_rays", new Integer(1)); - parameterDescriptions.put("rt_max_rays", "Max path rays"); - - // Ray Tracer - Max number of refractions - parameters.put("rt_max_refractions", new Integer(1)); - parameterDescriptions.put("rt_max_refractions", "Max refractions"); - - // Ray Tracer - Max number of reflections - parameters.put("rt_max_reflections", new Integer(1)); - parameterDescriptions.put("rt_max_reflections", "Max reflections"); - - // Ray Tracer - Max number of diffractions - parameters.put("rt_max_diffractions", new Integer(0)); - parameterDescriptions.put("rt_max_diffractions", "Max diffractions"); - - // Ray Tracer - Use scattering - //parameters.put("rt_use_scattering", new Boolean(false)); // TODO Not used yet - //parameterDescriptions.put("rt_use_scattering", "Use simple scattering"); - - // Ray Tracer - Refraction coefficient - parameters.put("rt_refrac_coefficient", new Double(-3)); - parameterDescriptions.put("rt_refrac_coefficient", "Refraction coefficient (dB)"); - - // Ray Tracer - Reflection coefficient - parameters.put("rt_reflec_coefficient", new Double(-5)); - parameterDescriptions.put("rt_reflec_coefficient", "Reflection coefficient (dB)"); - - // Ray Tracer - Diffraction coefficient - parameters.put("rt_diffr_coefficient", new Double(-10)); - parameterDescriptions.put("rt_diffr_coefficient", "Diffraction coefficient (dB)"); - - // Ray Tracer - Scattering coefficient - //parameters.put("rt_scatt_coefficient", new Double(-20)); // TODO Not used yet - //parameterDescriptions.put("rt_scatt_coefficient", "!! Scattering coefficient (dB)"); - - // Shadowing - Obstacle Attenuation constant - parameters.put("obstacle_attenuation", new Double(-3)); - parameterDescriptions.put("obstacle_attenuation", "Obstacle attenuation (dB/m)"); - } - - /** - * Adds a settings observer to this channel model. - * Every time the settings are changed all observers - * will be notified. - * - * @param obs New observer - */ - public void addSettingsObserver(Observer obs) { - settingsObservable.addObserver(obs); - } - - /** - * Deletes an earlier registered setting observer. - * - * @param osb - * Earlier registered observer - */ - public void deleteSettingsObserver(Observer obs) { - settingsObservable.deleteObserver(obs); - } - - /** - * Remove all previously registered obstacles - */ - public void removeAllObstacles() { - myObstacleWorld.removeAll(); - settingsObservable.notifySettingsChanged(); - } - - /** - * Add new obstacle with a rectangle shape. - * Notifies observers of the new obstacle. - * - * @param startX Low X coordinate - * @param startY Low Y coordinate - * @param width Width of obstacle - * @param height Height of obstacle - */ - public void addRectObstacle(double startX, double startY, double width, double height) { - addRectObstacle(startX, startY, width, height, true); - } - - /** - * Add new obstacle with a rectangle shape. - * Notifies observers depending on given notify argument. - * - * @param startX Low X coordinate - * @param startY Low Y coordinate - * @param width Width of obstacle - * @param height Height of obstacle - * @param notify If true, notifies all observers of this new obstacle - */ - public void addRectObstacle(double startX, double startY, double width, double height, boolean notify) { - myObstacleWorld.addObstacle(startX, startY, width, height); - - if (notify) - settingsObservable.notifySettingsChanged(); - } - - /** - * @return Number of registered obstacles - */ - public int getNumberOfObstacles() { - return myObstacleWorld.getNrObstacles(); - } - - /** - * Returns an obstacle at given position - * @param i Obstacle position - * @return Obstacle - */ - public Rectangle2D getObstacle(int i) { - return myObstacleWorld.getObstacle(i); - } - - /** - * Returns a parameter value - * - * @param identifier Parameter identifier - * @return Current parameter value - */ - public Object getParameterValue(String id) { - Object value = parameters.get(id); - if (value == null) { - logger.fatal("No parameter with id:" + id + ", aborting"); - return null; - } - return value; - } - - /** - * Returns a double parameter value - * - * @param identifier Parameter identifier - * @return Current parameter value - */ - public double getParameterDoubleValue(String id) { - return ((Double) getParameterValue(id)).doubleValue(); - } - - /** - * Returns an integer parameter value - * - * @param identifier Parameter identifier - * @return Current parameter value - */ - public int getParameterIntegerValue(String id) { - return ((Integer) getParameterValue(id)).intValue(); - } - - /** - * Returns a boolean parameter value - * - * @param identifier Parameter identifier - * @return Current parameter value - */ - public boolean getParameterBooleanValue(String id) { - return ((Boolean) getParameterValue(id)).booleanValue(); - } - - /** - * Saves a new parameter value - * - * @param id Parameter identifier - * @param newValue New parameter value - */ - public void setParameterValue(String id, Object newValue) { - if (!parameters.containsKey(id)) { - logger.fatal("No parameter with id:" + id + ", aborting"); - return; - } - parameters.put(id, newValue); - - // Guessing we need to recalculate input to FSPL+Output power - needToPrecalculateFSPL = true; - needToPrecalculateOutputPower = true; - - settingsObservable.notifySettingsChanged(); - } - - /** - * Returns a parameter description - * - * @param identifier Parameter identifier - * @return Current parameter description - */ - public String getParameterDescription(String id) { - Object value = parameterDescriptions.get(id); - if (value == null) { - logger.fatal("No parameter description with id:" + id + ", aborting"); - return null; - } - return ((String) value); - } - - /** - * When this method is called all settings observers - * will be notified. - */ - public void notifySettingsChanged() { - settingsObservable.notifySettingsChanged(); - } - - /** - * Returns the Free Space Path Loss factor (in dB), by using - * parts of the Friis equation. (FSPL <= 0) - * - * @param distance Distance from transmitter to receiver - * @return FSPL factor - */ - protected double getFSPL(double distance) { - // From Friis equation: - // Pr(d) = Pt * (Gt * Gr * w2) / ( (4*PI)2 * d2 * L) - // For FSPL, ignoring Pt, Gt, Gr, L: - // Pr(d) = 1 * (1 * 1 * w2) / ( (4*PI)2 * d2 * 1) - // Pr(d) = w2 / ( (4*PI)2 * d2) - // Pr_dB(d) = 20*log10(w) - 20*log10(4*PI) - 20*log10(d) - - if (needToPrecalculateFSPL) { - double w = getParameterDoubleValue("wavelength"); - paramFSPL = 20*Math.log10(w) - 20*Math.log10(4*Math.PI); - needToPrecalculateFSPL = false; - } - - return Math.min(0.0, paramFSPL - 20*Math.log10(distance)); - } - - - /** - * Returns the subset of a given line, that is intersecting the given rectangle. - * This method returns null if the line does not intersect the rectangle. - * The given line is defined by the given (x1, y1) -> (x2, y2). - * - * @param x1 Line start point X - * @param y1 Line start point Y - * @param x2 Line end point X - * @param y2 Line epoint Y - * @param rectangle Rectangle which line may intersect - * @return Intersection line of given line and rectangle (or null) - */ - private Line2D getIntersectionLine(double x1, double y1, double x2, double y2, Rectangle2D rectangle) { - - // Check if entire line is inside rectangle - if (rectangle.contains(x1, y1) && rectangle.contains(x2, y2)) { - return new Line2D.Double(x1, y1, x2, y2); - } - - // Get rectangle and test lines - Line2D rectangleLower = new Line2D.Double(rectangle.getMinX(), rectangle.getMinY(), rectangle.getMaxX(), rectangle.getMinY()); - Line2D rectangleUpper = new Line2D.Double(rectangle.getMinX(), rectangle.getMaxY(), rectangle.getMaxX(), rectangle.getMaxY()); - Line2D rectangleLeft = new Line2D.Double(rectangle.getMinX(), rectangle.getMinY(), rectangle.getMinX(), rectangle.getMaxY()); - Line2D rectangleRight = new Line2D.Double(rectangle.getMaxX(), rectangle.getMinY(), rectangle.getMaxX(), rectangle.getMaxY()); - Line2D testLine = new Line2D.Double(x1, y1, x2, y2); - - // Check which sides of the rectangle the test line passes through - Vector intersectedSides = new Vector(); - - if (rectangleLower.intersectsLine(testLine)) - intersectedSides.add(rectangleLower); - - if (rectangleUpper.intersectsLine(testLine)) - intersectedSides.add(rectangleUpper); - - if (rectangleLeft.intersectsLine(testLine)) - intersectedSides.add(rectangleLeft); - - if (rectangleRight.intersectsLine(testLine)) - intersectedSides.add(rectangleRight); - - // If no sides are intersected, return null (no intersection) - if (intersectedSides.isEmpty()) { - return null; - } - - // Calculate all resulting line points (should be 2) - Vector intersectingLinePoints = new Vector(); - - for (int i=0; i < intersectedSides.size(); i++) { - intersectingLinePoints.add( - getIntersectionPoint(testLine, intersectedSides.get(i)) - ); - } - - // If only one side was intersected, one point must be inside rectangle - if (intersectingLinePoints.size() == 1) { - if (rectangle.contains(x1, y1)) { - intersectingLinePoints.add(new Point2D.Double(x1, y1)); - } else if (rectangle.contains(x2, y2)) { - intersectingLinePoints.add(new Point2D.Double(x2, y2)); - } else { - // Border case, no intersection line - return null; - } - } - - if (intersectingLinePoints.size() != 2) { - // We should have 2 line points! - logger.warn("Intersecting points != 2"); - return null; - } - - if (intersectingLinePoints.get(0).distance(intersectingLinePoints.get(1)) < 0.001) - return null; - - return new Line2D.Double( - intersectingLinePoints.get(0), - intersectingLinePoints.get(1) - ); - } - - /** - * Returns the intersection point of the two given lines. - * - * @param firstLine First line - * @param secondLine Second line - * @return Intersection point of the two lines or null - */ - private Point2D getIntersectionPoint(Line2D firstLine, Line2D secondLine) { - double dx1 = firstLine.getX2() - firstLine.getX1(); - double dy1 = firstLine.getY2() - firstLine.getY1(); - double dx2 = secondLine.getX2() - secondLine.getX1(); - double dy2 = secondLine.getY2() - secondLine.getY1(); - double det = (dx2*dy1-dy2*dx1); - - if (det == 0.0) - // Lines parallell, not intersecting - return null; - - double mu = ((firstLine.getX1() - secondLine.getX1())*dy1 - (firstLine.getY1() - secondLine.getY1())*dx1)/det; - if (mu >= 0.0 && mu <= 1.0) { - Point2D.Double intersectionPoint = new Point2D.Double((secondLine.getX1() + mu*dx2), - (secondLine.getY1() + mu*dy2)); - - return intersectionPoint; - } - - // Lines not intersecting withing segments - return null; - } - - /** - * Returns the intersection point of the two given lines when streched to infinity. - * - * @param firstLine First line - * @param secondLine Second line - * @return Intersection point of the two infinite lines or null if parallell - */ - private Point2D getIntersectionPointInfinite(Line2D firstLine, Line2D secondLine) { - double dx1 = firstLine.getX2() - firstLine.getX1(); - double dy1 = firstLine.getY2() - firstLine.getY1(); - double dx2 = secondLine.getX2() - secondLine.getX1(); - double dy2 = secondLine.getY2() - secondLine.getY1(); - double det = (dx2*dy1-dy2*dx1); - - if (det == 0.0) - // Lines parallell, not intersecting - return null; - - double mu = ((firstLine.getX1() - secondLine.getX1())*dy1 - (firstLine.getY1() - secondLine.getY1())*dx1)/det; - Point2D.Double intersectionPoint = new Point2D.Double((secondLine.getX1() + mu*dx2), - (secondLine.getY1() + mu*dy2)); - - return intersectionPoint; - } - - /** - * This method builds a tree structure with all visible lines from a given source. - * It is recursive and depends on the given ray data argument, which holds information - * about maximum number of recursions. - * Each element in the tree is either produced from a refraction, reflection or a diffraction - * (except for the absolute source which is neither), and holds a point and a line. - * - * @param rayData Holds information about the incident ray - * @return Tree of all visibles lines - */ - private DefaultMutableTreeNode buildVisibleLinesTree(RayData rayData) { - DefaultMutableTreeNode thisTree = new DefaultMutableTreeNode(); - thisTree.setUserObject(rayData); - - // If no more rays may be produced there if no need to search for visible lines - if (rayData.getSubRaysLimit() <= 0) { - return thisTree; - } - - Point2D source = rayData.getSourcePoint(); - Line2D line = rayData.getLine(); - - // Find all visible lines - Vector visibleSides = getAllVisibleSides( - source.getX(), - source.getY(), - null, - line - ); - - // Create refracted subtrees - if (rayData.getRefractedSubRaysLimit() > 0 && visibleSides != null) { - Enumeration visibleSidesEnum = visibleSides.elements(); - while (visibleSidesEnum.hasMoreElements()) { - Line2D refractingSide = visibleSidesEnum.nextElement(); - - // Keeping old source, but looking through this line to see behind it - - // Recursively build and add subtrees - RayData newRayData = new RayData( - RayData.RayType.REFRACTION, - source, - refractingSide, - rayData.getSubRaysLimit() - 1, - rayData.getRefractedSubRaysLimit() - 1, - rayData.getReflectedSubRaysLimit(), - rayData.getDiffractedSubRaysLimit() - ); - DefaultMutableTreeNode subTree = buildVisibleLinesTree(newRayData); - - thisTree.add(subTree); - } - } - - // Create reflection subtrees - if (rayData.getReflectedSubRaysLimit() > 0 && visibleSides != null) { - Enumeration visibleSidesEnum = visibleSides.elements(); - while (visibleSidesEnum.hasMoreElements()) { - Line2D reflectingSide = visibleSidesEnum.nextElement(); - - // Create new pseudo-source - Rectangle2D bounds = reflectingSide.getBounds2D(); - double newPsuedoSourceX = source.getX(); - double newPsuedoSourceY = source.getY(); - if (bounds.getHeight() > bounds.getWidth()) - newPsuedoSourceX = 2*reflectingSide.getX1() - newPsuedoSourceX; - else - newPsuedoSourceY = 2*reflectingSide.getY1() - newPsuedoSourceY; - - // Recursively build and add subtrees - RayData newRayData = new RayData( - RayData.RayType.REFLECTION, - new Point2D.Double(newPsuedoSourceX, newPsuedoSourceY), - reflectingSide, - rayData.getSubRaysLimit() - 1, - rayData.getRefractedSubRaysLimit(), - rayData.getReflectedSubRaysLimit() - 1, - rayData.getDiffractedSubRaysLimit() - ); - DefaultMutableTreeNode subTree = buildVisibleLinesTree(newRayData); - - thisTree.add(subTree); - } - } - - // Get possible diffraction sources - Vector diffractionSources = null; - if (rayData.getDiffractedSubRaysLimit() > 0) { - diffractionSources = getAllDiffractionSources(visibleSides); - } - - // Create diffraction subtrees - if (rayData.getDiffractedSubRaysLimit() > 0 && diffractionSources != null) { - Enumeration diffractionSourcesEnum = diffractionSources.elements(); - while (diffractionSourcesEnum.hasMoreElements()) { - Point2D diffractionSource = diffractionSourcesEnum.nextElement(); - - // Recursively build and add subtrees - RayData newRayData = new RayData( - RayData.RayType.DIFFRACTION, - diffractionSource, - null, - rayData.getSubRaysLimit() - 1, - rayData.getRefractedSubRaysLimit(), - rayData.getReflectedSubRaysLimit(), - rayData.getDiffractedSubRaysLimit() - 1 - ); - DefaultMutableTreeNode subTree = buildVisibleLinesTree(newRayData); - - thisTree.add(subTree); - } - } - - return thisTree; - } - - /** - * Returns a vector of ray paths from given origin to given destination. - * Each ray path consists of a vector of points (including source and destination). - * - * @param origin Ray paths origin - * @param dest Ray paths destination - * @param visibleLinesTree Information about all visible lines generated by buildVisibleLinesTree() - * @see #buildVisibleLinesTree(RayData) - * @return All ray paths from origin to destnation - */ - private Vector getConnectingPaths(Point2D origin, Point2D dest, DefaultMutableTreeNode visibleLinesTree) { - Vector allPaths = new Vector(); - - // Analyse the possible paths to find which actually reached destination - Enumeration treeEnum = visibleLinesTree.breadthFirstEnumeration(); - while (treeEnum.hasMoreElements()) { - // For every element, - // check if it is the origin, a diffraction, refraction or a reflection source - DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) treeEnum.nextElement(); - RayData rayData = (RayData) treeNode.getUserObject(); - Point2D sourcePoint = rayData.getSourcePoint(); - Line2D line = rayData.getLine(); - RayData.RayType type = rayData.getType(); - - Line2D pseudoSourceToDest = new Line2D.Double(sourcePoint, dest); - boolean directPathExists = false; - Point2D justBeforeDestination = null; - - // Get ray path point just before destination (if path exists at all) - if (type == RayData.RayType.ORIGIN) { - - // Check if direct path exists - justBeforeDestination = sourcePoint; - - if (!getParameterBooleanValue("rt_disallow_direct_path")) - directPathExists = isDirectPath(justBeforeDestination, dest); - else - directPathExists = false; - - } else if (type == RayData.RayType.REFRACTION && pseudoSourceToDest.intersectsLine(line)) { - - // Destination is inside refraction interval - justBeforeDestination = getIntersectionPoint(pseudoSourceToDest, line); - - // Check if direct path exists (but ignore when leaving obstacle) - directPathExists = isDirectPath(justBeforeDestination, dest); - - } else if (type == RayData.RayType.REFLECTION && pseudoSourceToDest.intersectsLine(line)) { - - // Destination is inside reflection interval - justBeforeDestination = getIntersectionPoint(pseudoSourceToDest, line); - - // Check if direct path exists (ignore reflection line) - directPathExists = isDirectPath(justBeforeDestination, dest); - - } else if (type == RayData.RayType.DIFFRACTION) { - - // Check if direct path exists (travelling through object not allowed - justBeforeDestination = sourcePoint; - directPathExists = isDirectPath(justBeforeDestination, dest); - - } - - // If a direct path exists, traverse up tree to find entire path - if (directPathExists) { - - // Create new empty ray path - boolean pathBroken = false; - RayPath currentPath = new RayPath(); - - // Add those parts we already know - currentPath.addPoint(dest, RayData.RayType.DESTINATION); - currentPath.addPoint(justBeforeDestination, type); - - Point2D lastPoint = dest; - Point2D newestPoint = justBeforeDestination; - - // Check that this ray subpath is long enough to be considered - if (newestPoint.distance(lastPoint) < 0.01 && type != RayData.RayType.ORIGIN) { - pathBroken = true; - } - - // Subpath must be double-direct if from diffraction - if (type == RayData.RayType.DIFFRACTION && !isDirectPath(lastPoint, newestPoint)) { - pathBroken = true; - } - - // Data used when traversing path - DefaultMutableTreeNode currentlyTracedNode = treeNode; - RayData currentlyTracedRayData = (RayData) currentlyTracedNode.getUserObject(); - RayData.RayType currentlyTracedNodeType = currentlyTracedRayData.getType(); - Point2D currentlyTracedSource = currentlyTracedRayData.getSourcePoint(); - Line2D currentlyTracedLine = currentlyTracedRayData.getLine(); - - - // Traverse upwards until origin found - while (!pathBroken && currentlyTracedNodeType != RayData.RayType.ORIGIN) { - - // Update new ray data - currentlyTracedNode = (DefaultMutableTreeNode) currentlyTracedNode.getParent(); - currentlyTracedRayData = (RayData) currentlyTracedNode.getUserObject(); - currentlyTracedNodeType = currentlyTracedRayData.getType(); - currentlyTracedSource = currentlyTracedRayData.getSourcePoint(); - currentlyTracedLine = currentlyTracedRayData.getLine(); - - if (currentlyTracedNodeType == RayData.RayType.ORIGIN) { - // We finally found the path origin, path ends here - lastPoint = newestPoint; - newestPoint = origin; - - currentPath.addPoint(newestPoint, currentlyTracedNodeType); - - // Check that this ray subpath is long enough to be considered - if (newestPoint.distance(lastPoint) < 0.01) - pathBroken = true; - - } else { - // Trace further up in the tree - - if (currentlyTracedNodeType == RayData.RayType.REFRACTION || currentlyTracedNodeType == RayData.RayType.REFLECTION) { - // Traced tree element is a reflection/refraction - get intersection point and keep climbing - lastPoint = newestPoint; - - Line2D newToOldIntersection = new Line2D.Double(currentlyTracedSource, lastPoint); - newestPoint = getIntersectionPointInfinite(newToOldIntersection, currentlyTracedLine); - - } else { - // Traced tree element is a diffraction - save point and keep climbing - lastPoint = newestPoint; - newestPoint = currentlyTracedSource; - } - - currentPath.addPoint(newestPoint, currentlyTracedNodeType); - - // Check that this ray subpath is long enough to be considered - if (newestPoint == null || lastPoint == null || newestPoint.distance(lastPoint) < 0.01) - pathBroken = true; - } - - // Subpath must be double-direct if from diffraction - if (currentlyTracedNodeType == RayData.RayType.DIFFRACTION && !isDirectPath(lastPoint, newestPoint)) { - pathBroken = true; - } - - if (pathBroken) - break; - } - - // Save ray path - if (!pathBroken) { - allPaths.add(currentPath); - - // Stop here if no other paths should be considered - if (type == RayData.RayType.ORIGIN && getParameterBooleanValue("rt_ignore_non_direct")) { - return allPaths; - } - - } - - } - } - - return allPaths; - } - - /** - * True if a line drawn from the given source and given destination does - * not intersect with any obstacle outer lines in the current obstacle world. - * This method only checks for intersection with the obstacles lines "visible" - * from source. Hence, if source is inside an obstacle, that obstacles will - * not cause this method to return false. (Note that method is not symmetric) - * - * @param source Source - * @param dest Destination - * @return True if no obstacles between source and destination - */ - private boolean isDirectPath(Point2D source, Point2D dest) { - Line2D sourceToDest = new Line2D.Double(source, dest); - - // Get angle - double deltaX = dest.getX() - source.getX(); - double deltaY = dest.getY() - source.getY(); - double angleSourceToDest = Math.atan2(deltaY, deltaX); - - // Get all visible sides near angle - Vector visibleSides = getAllVisibleSides( - source.getX(), - source.getY(), - new AngleInterval(angleSourceToDest - 0.1, angleSourceToDest + 0.1), - null - ); - - // Check for intersections - if (visibleSides != null) { - for (int i=0; i < visibleSides.size(); i++) { - if (visibleSides.get(i).intersectsLine(sourceToDest)) { - // Check that intersection point is not destination - Point2D intersectionPoint = getIntersectionPointInfinite(visibleSides.get(i), sourceToDest); - if (dest.distance(intersectionPoint) > 0.01) - return false; - } - } - } - - return true; - } - - /** - * Returns the Fast fading factor (in dB), which depends on - * the multiple paths from source to destination via reflections - * on registered obstacles. - * TODO Only first-order multipath... - * - * @param sourceX Transmitter X coordinate - * @param sourceY Transmitter Y coordinate - * @param destX Receiver X coordinate - * @param destY Receiver Y coordinate - * @return Slow fading factor - */ - protected double getFastFading(double sourceX, double sourceY, double destX, double destY) { - Point2D dest = new Point2D.Double(destX, destY); - Point2D source = new Point2D.Double(sourceX, sourceY); - - // Destination inside an obstacle? => no reflection factor - for (int i=0; i < myObstacleWorld.getNrObstacles(); i++) { - if (myObstacleWorld.getObstacle(i).contains(dest)) { - //logger.debug("Destination inside obstacle, aborting fast fading"); - return 0; - } - } - - return 0; - } - - - /** - * Returns all possible diffraction sources, by checking which - * of the endpoints of the given visible lines that are on a corner - * of a obstacle structure. - * - * @param allVisibleLines Lines which may hold diffraction sources - * @return All diffraction sources - */ - private Vector getAllDiffractionSources(Vector allVisibleLines) { - Vector allDiffractionSources = new Vector(); - Enumeration allVisibleLinesEnum = allVisibleLines.elements(); - - while (allVisibleLinesEnum.hasMoreElements()) { - Line2D visibleLine = allVisibleLinesEnum.nextElement(); - - // Check both end points of line for possible diffraction point - if (myObstacleWorld.pointIsNearCorner(visibleLine.getP1())) { - allDiffractionSources.add(visibleLine.getP1()); - } - if (myObstacleWorld.pointIsNearCorner(visibleLine.getP2())) { - allDiffractionSources.add(visibleLine.getP2()); - } - } - - return allDiffractionSources; - } - - /** - * Return all obstacle sides visible from given source when looking - * in the given angle interval. - * The sides may partly be shadowed by other obstacles. - * If the angle interval is null, it will be regarded as the entire interval - * If the line argument is non-null, all returned lines will be on the far side - * of this line, as if one was looking through that line. - * - * @param sourceX Source X - * @param sourceY Source Y - * @param angleInterval Angle interval (or null) - * @param lookThrough Line to look through (or null) - * @return All visible sides - */ - private Vector getAllVisibleSides(double sourceX, double sourceY, AngleInterval angleInterval, Line2D lookThrough) { - Point2D source = new Point2D.Double(sourceX, sourceY); - - // Check if results were already calculated earlier - for (int i=0; i < calculatedVisibleSidesSources.size(); i++) { - if ( - // Compare sources - source.equals(calculatedVisibleSidesSources.get(i)) && - - // Compare angle intervals - (angleInterval == calculatedVisibleSidesAngleIntervals.get(i) || - angleInterval != null && angleInterval.equals(calculatedVisibleSidesAngleIntervals.get(i)) ) && - - // Compare lines - (lookThrough == calculatedVisibleSidesLines.get(i) || - lookThrough != null && lookThrough.equals(calculatedVisibleSidesLines.get(i)) ) - ) { - // Move to top of list - Point2D oldSource = calculatedVisibleSidesSources.remove(i); - Line2D oldLine = calculatedVisibleSidesLines.remove(i); - AngleInterval oldAngleInterval = calculatedVisibleSidesAngleIntervals.remove(i); - Vector oldVisibleLines = calculatedVisibleSides.remove(i); - - calculatedVisibleSidesSources.add(0, oldSource); - calculatedVisibleSidesLines.add(0, oldLine); - calculatedVisibleSidesAngleIntervals.add(0, oldAngleInterval); - calculatedVisibleSides.add(0, oldVisibleLines); - - // Return old results - return oldVisibleLines; - } - } - - Vector visibleLines = new Vector(); - Vector unhandledAngles = new Vector(); - - if (lookThrough != null) { - if (angleInterval == null) - unhandledAngles.add(AngleInterval.getAngleIntervalOfLine(source, lookThrough)); - else - unhandledAngles.add(AngleInterval.getAngleIntervalOfLine(source, lookThrough).intersectWith(angleInterval)); - } else { - if (angleInterval == null) - unhandledAngles.add(new AngleInterval(0, 2*Math.PI)); - else - unhandledAngles.add(angleInterval); - } - - // Do forever (will break when no more unhandled angles exist) - while (!unhandledAngles.isEmpty()) { - - // While unhandled angles still exist, keep searching for visible lines - while (!unhandledAngles.isEmpty()) { - //logger.info("Beginning of while-loop, unhandled angles left = " + unhandledAngles.size()); - AngleInterval angleIntervalToCheck = unhandledAngles.firstElement(); - - // Check that interval is not empty or "infinite small" - if (angleIntervalToCheck == null || angleIntervalToCheck.isEmpty()) { - //logger.info("Angle interval (almost) empty, ignoring"); - unhandledAngles.remove(angleIntervalToCheck); - break; - } - - // <<<< Get visible obstacle candidates inside this angle interval >>>> - Vector visibleObstacleCandidates = - myObstacleWorld.getAllObstaclesInAngleInterval(source, angleIntervalToCheck); - - //logger.info("Obstacle candidates count = " + visibleObstacleCandidates.size()); - if (visibleObstacleCandidates.isEmpty()) { - //logger.info("Visible obstacles candidates empty"); - unhandledAngles.remove(angleIntervalToCheck); - break; // Restart without this angle - } - - // <<<< Get visible line candidates of these obstacles >>>> - Vector visibleLineCandidates = new Vector(); - for (int i=0; i < visibleObstacleCandidates.size(); i++) { - Rectangle2D obstacle = visibleObstacleCandidates.get(i); - int outcode = obstacle.outcode(source); - - if ((outcode & Rectangle2D.OUT_BOTTOM) != 0) - visibleLineCandidates.add( - new Line2D.Double(obstacle.getMinX(), obstacle.getMaxY(), obstacle.getMaxX(), obstacle.getMaxY())); - - if ((outcode & Rectangle2D.OUT_TOP) != 0) - visibleLineCandidates.add( - new Line2D.Double(obstacle.getMinX(), obstacle.getMinY(), obstacle.getMaxX(), obstacle.getMinY())); - - if ((outcode & Rectangle2D.OUT_LEFT) != 0) - visibleLineCandidates.add( - new Line2D.Double(obstacle.getMinX(), obstacle.getMinY(), obstacle.getMinX(), obstacle.getMaxY())); - - if ((outcode & Rectangle2D.OUT_RIGHT) != 0) - visibleLineCandidates.add( - new Line2D.Double(obstacle.getMaxX(), obstacle.getMinY(), obstacle.getMaxX(), obstacle.getMaxY())); - } - //logger.info("Line candidates count = " + visibleLineCandidates.size()); - if (visibleLineCandidates.isEmpty()) { - //logger.info("Visible line candidates empty"); - unhandledAngles.remove(angleIntervalToCheck); - break; // Restart without this angle - } - - // <<<< Get cropped visible line candidates of these lines >>>> - Vector croppedVisibleLineCandidates = new Vector(); - for (int i=0; i < visibleLineCandidates.size(); i++) { - Line2D lineCandidate = visibleLineCandidates.get(i); - - // Create angle interval of this line - AngleInterval lineAngleInterval = AngleInterval.getAngleIntervalOfLine(source, lineCandidate); - - AngleInterval intersectionInterval = null; - - // Add entire line if it is fully inside our visible angle interval - if (angleIntervalToCheck.contains(lineAngleInterval)) { - - if (lookThrough != null) { - // Check if the candidate is "equal" to the see through line - if (Math.abs(lineCandidate.getX1() - lookThrough.getX1()) + - Math.abs(lineCandidate.getY1() - lookThrough.getY1()) + - Math.abs(lineCandidate.getX2() - lookThrough.getX2()) + - Math.abs(lineCandidate.getY2() - lookThrough.getY2()) < 0.01) { - // See through line and candidate line are the same - skip this candidate - } - - // Check if the candidate is on our side of the see through line - else if (new Line2D.Double( - lineCandidate.getBounds2D().getCenterX(), - lineCandidate.getBounds2D().getCenterY(), - sourceX, - sourceY - ).intersectsLine(lookThrough)) { - croppedVisibleLineCandidates.add(lineCandidate); - } // else Skip line - } else croppedVisibleLineCandidates.add(lineCandidate); - - } - - // Add part of line if it is partly inside our visible angle interval - else if ((intersectionInterval = lineAngleInterval.intersectWith(angleIntervalToCheck)) != null) { - - // Get lines towards the visible segment - Line2D lineToStartAngle = AngleInterval.getDirectedLine( - source, - intersectionInterval.getStartAngle(), - 1.0 - ); - Line2D lineToEndAngle = AngleInterval.getDirectedLine( - source, - intersectionInterval.getEndAngle(), - 1.0 - ); - - // Calculate intersection points - Point2D intersectionStart = getIntersectionPointInfinite( - lineCandidate, - lineToStartAngle - ); - Point2D intersectionEnd = getIntersectionPointInfinite( - lineCandidate, - lineToEndAngle - ); - - if ( - intersectionStart != null && - intersectionEnd != null && - intersectionStart.distance(intersectionEnd) > 0.001 // Rounding error limit (1 mm) - ) { - - Line2D newCropped = new Line2D.Double(intersectionStart, intersectionEnd); - - if (lookThrough != null) { - // Check if the candidate is "equal" to the see through line - if (Math.abs(newCropped.getX1() - lookThrough.getX1()) + - Math.abs(newCropped.getY1() - lookThrough.getY1()) + - Math.abs(newCropped.getX2() - lookThrough.getX2()) + - Math.abs(newCropped.getY2() - lookThrough.getY2()) < 0.01) { - // See through line and candidate line are the same - skip this candidate - } - - // Check if the candidate is on our side of the see through line - else if (new Line2D.Double( - newCropped.getBounds2D().getCenterX(), - newCropped.getBounds2D().getCenterY(), - sourceX, - sourceY - ).intersectsLine(lookThrough)) { - croppedVisibleLineCandidates.add(newCropped); - } // else Skip line - } else croppedVisibleLineCandidates.add(newCropped); - - } - } - - // Skip line completely if not in our visible angle interval - else { - } - } - //logger.info("Cropped line candidates count = " + croppedVisibleLineCandidates.size()); - if (croppedVisibleLineCandidates.isEmpty()) { - //logger.info("Cropped visible line candidates empty"); - unhandledAngles.remove(angleIntervalToCheck); - break; // Restart without this angle - } - - // <<<< Get visible lines from these line candidates >>>> - for (int i=0; i < croppedVisibleLineCandidates.size(); i++) { - Line2D visibleLineCandidate = croppedVisibleLineCandidates.get(i); - AngleInterval visibleLineCandidateAngleInterval = - AngleInterval.getAngleIntervalOfLine(source, visibleLineCandidate).intersectWith(angleIntervalToCheck); - - //logger.info("Incoming angle interval " + angleIntervalToCheck); - //logger.info(". => line interval " + visibleLineCandidateAngleInterval); - - // Area to test for shadowing objects - GeneralPath testArea = new GeneralPath(); - testArea.moveTo((float) sourceX, (float) sourceY); - testArea.lineTo((float) visibleLineCandidate.getX1(), (float) visibleLineCandidate.getY1()); - testArea.lineTo((float) visibleLineCandidate.getX2(), (float) visibleLineCandidate.getY2()); - testArea.closePath(); - - // Does any other line shadow this line? - boolean unshadowed = true; - boolean unhandledAnglesChanged = false; - for (int j=0; j < croppedVisibleLineCandidates.size(); j++) { - - // Create shadow rectangle - Line2D shadowLineCandidate = croppedVisibleLineCandidates.get(j); - Rectangle2D shadowRectangleCandidate = shadowLineCandidate.getBounds2D(); - double minDelta = 0.01*Math.max( - shadowRectangleCandidate.getWidth(), - shadowRectangleCandidate.getHeight() - ); - shadowRectangleCandidate.add( - shadowRectangleCandidate.getCenterX() + minDelta, - shadowRectangleCandidate.getCenterY() + minDelta - ); - - // Find the shortest of the two - double shadowDistance = - shadowLineCandidate.getP1().distance(source) + - shadowLineCandidate.getP2().distance(source); - - double visibleDistance = - visibleLineCandidate.getP1().distance(source) + - visibleLineCandidate.getP2().distance(source); - - double shadowCloseDistance = - Math.min( - shadowLineCandidate.getP1().distance(source), - shadowLineCandidate.getP2().distance(source)); - - double visibleFarDistance = - Math.max( - visibleLineCandidate.getP1().distance(source), - visibleLineCandidate.getP2().distance(source)); - - // Does shadow rectangle intersect test area? - if (visibleLineCandidate != shadowLineCandidate && - testArea.intersects(shadowRectangleCandidate) && - shadowCloseDistance <= visibleFarDistance) { - - // Shadow line candidate seems to shadow (part of) our visible candidate - AngleInterval shadowLineCandidateAngleInterval = - AngleInterval.getAngleIntervalOfLine(source, shadowLineCandidate).intersectWith(angleIntervalToCheck); - - if (shadowLineCandidateAngleInterval.contains(visibleLineCandidateAngleInterval)) { - // Covers us entirely, do nothing - - // Special case, both shadow and visible candidate have the same interval - if (visibleLineCandidateAngleInterval.contains(shadowLineCandidateAngleInterval)) { - - if (visibleDistance > shadowDistance) { - unshadowed = false; - break; - } - } else { - unshadowed = false; - break; - } - - } else if (visibleLineCandidateAngleInterval.intersects(shadowLineCandidateAngleInterval)) { - // Covers us partly, split angle interval - Vector newIntervalsToAdd = new Vector(); - - // Create angle interval of intersection between shadow and visible candidate - AngleInterval intersectedInterval = - visibleLineCandidateAngleInterval.intersectWith(shadowLineCandidateAngleInterval); - if (intersectedInterval != null) { - Vector tempVector1 = - AngleInterval.intersect(unhandledAngles, intersectedInterval); - - if (tempVector1 != null) - for (int k=0; k < tempVector1.size(); k++) - if (tempVector1.get(k) != null && !tempVector1.get(k).isEmpty()) { - newIntervalsToAdd.add(tempVector1.get(k)); - } - } - - // Add angle interval of visible candidate without shadow candidate - Vector tempVector2 = - visibleLineCandidateAngleInterval.subtract(shadowLineCandidateAngleInterval); - if (tempVector2 != null) - for (int k=0; k < tempVector2.size(); k++) - if (tempVector2.get(k) != null && !tempVector2.get(k).isEmpty()) - newIntervalsToAdd.addAll(AngleInterval.intersect(unhandledAngles, tempVector2.get(k))); - - // Subtract angle interval of visible candidate - unhandledAngles = AngleInterval.subtract(unhandledAngles, visibleLineCandidateAngleInterval); - unhandledAnglesChanged = true; - - // Add new angle intervals - //logger.info("Split angle interval: " + visibleLineCandidateAngleInterval); - for (int k=0; k < newIntervalsToAdd.size(); k++) { - if (newIntervalsToAdd.get(k) != null && !newIntervalsToAdd.get(k).isEmpty()) { - //logger.info("> into: " + newIntervalsToAdd.get(k)); - unhandledAngles.add(newIntervalsToAdd.get(k)); - unhandledAnglesChanged = true; - } - } - - unshadowed = false; - break; - } else { - // Not intersecting after all, just ignore this - } - } - - if (!unshadowed) - break; - } - - if (unhandledAnglesChanged) { - //logger.info("Unhandled angles changed, restarting.."); - break; - } - - if (unshadowed) { - // No other lines shadow this line => this line must be visible! - - unhandledAngles = AngleInterval.subtract(unhandledAngles, visibleLineCandidateAngleInterval); - visibleLines.add(visibleLineCandidate); - - //logger.info("Added visible line and removed angle interval: " + visibleLineCandidateAngleInterval); - //logger.info("Number of visible lines sofar: " + visibleLines.size()); - break; - } - - } - - } - - } // End of outer loop - - // Save results in order to speed up later calculations - int size = calculatedVisibleSides.size(); - // Crop saved sides vectors - if (size >= maxSavedVisibleSides) { - calculatedVisibleSides.remove(size-1); - calculatedVisibleSidesSources.remove(size-1); - calculatedVisibleSidesAngleIntervals.remove(size-1); - calculatedVisibleSidesLines.remove(size-1); - } - - calculatedVisibleSides.add(0, visibleLines); - calculatedVisibleSidesSources.add(0, source); - calculatedVisibleSidesAngleIntervals.add(0, angleInterval); - calculatedVisibleSidesLines.add(0, lookThrough); - - return visibleLines; - } - - /** - * Calculates and returns the received signal strength (dBm) of a signal sent - * from the given source position to the given destination position as a - * random variable. This method uses current parameters such as transmitted - * power, obstacles, overall system loss etc. - * - * @param sourceX - * Source position X - * @param sourceY - * Source position Y - * @param destX - * Destination position X - * @param destY - * Destination position Y - * @return Received signal strength (dBm) random variable. The first value is - * the random variable mean, and the second is the variance. - */ - public double[] getReceivedSignalStrength(double sourceX, double sourceY, double destX, double destY) { - return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.SIGNAL_STRENGTH); - } - - // TODO Fix better data type support - private double[] getTransmissionData(double sourceX, double sourceY, double destX, double destY, TransmissionData dataType) { - Point2D source = new Point2D.Double(sourceX, sourceY); - Point2D dest = new Point2D.Double(destX, destY); - double accumulatedVariance = 0; - - // - Get all ray paths from source to destination - - RayData originRayData = new RayData( - RayData.RayType.ORIGIN, - source, - null, - getParameterIntegerValue("rt_max_rays"), - getParameterIntegerValue("rt_max_refractions"), - getParameterIntegerValue("rt_max_reflections"), - getParameterIntegerValue("rt_max_diffractions") - ); - - // TODO Current (changing) signal strength should be built into 'build visible lines' to speed up things! - - // Check if origin tree is already calculated and saved - DefaultMutableTreeNode visibleLinesTree = null; - visibleLinesTree = - buildVisibleLinesTree(originRayData); - - // Calculate all paths from source to destination, using above calculated tree - Vector allPaths = getConnectingPaths(source, dest, visibleLinesTree); - - if (inLoggingMode) { - logger.info("Saved rays:"); - Enumeration pathsEnum = allPaths.elements(); - while (pathsEnum.hasMoreElements()) { - RayPath currentPath = pathsEnum.nextElement(); - logger.info("* " + currentPath); - for (int i=0; i < currentPath.getSubPathCount(); i++) { - savedRays.add(currentPath.getSubPath(i)); - } - } - } - - // - Extract length and losses of each path - - double[] pathLengths = new double[allPaths.size()]; - double[] pathGain = new double[allPaths.size()]; - int bestSignalNr = -1; - double bestSignalPathLoss = 0; - for (int i=0; i < allPaths.size(); i++) { - RayPath currentPath = allPaths.get(i); - double accumulatedStraightLength = 0; - - for (int j=0; j < currentPath.getSubPathCount(); j++) { - Line2D subPath = currentPath.getSubPath(j); - double subPathLength = subPath.getP1().distance(subPath.getP2()); - RayData.RayType subPathStartType = currentPath.getType(j); - - // Type specific losses - // TODO Type specific losses depends on angles as well! - if (subPathStartType == RayData.RayType.REFRACTION) { - pathGain[i] += getParameterDoubleValue("rt_refrac_coefficient"); - } else if (subPathStartType == RayData.RayType.REFLECTION) { - pathGain[i] += getParameterDoubleValue("rt_reflec_coefficient"); - - // Add FSPL from last subpaths (if FSPL on individual rays) - if (!getParameterBooleanValue("rt_fspl_on_total_length") && accumulatedStraightLength > 0) { - pathGain[i] += getFSPL(accumulatedStraightLength); - } - accumulatedStraightLength = 0; // Reset straight length - } else if (subPathStartType == RayData.RayType.DIFFRACTION) { - pathGain[i] += getParameterDoubleValue("rt_diffr_coefficient"); - - // Add FSPL from last subpaths (if FSPL on individual rays) - if (!getParameterBooleanValue("rt_fspl_on_total_length") && accumulatedStraightLength > 0) { - pathGain[i] += getFSPL(accumulatedStraightLength); - } - accumulatedStraightLength = 0; // Reset straight length - } - accumulatedStraightLength += subPathLength; // Add length, FSPL should be calculated on total straight length - - // If ray starts with a refraction, calculate obstacle attenuation - if (subPathStartType == RayData.RayType.REFRACTION) { - // Ray passes through a wall, calculate distance through that wall - - // Fetch attenuation constant - double attenuationConstant = getParameterDoubleValue("obstacle_attenuation"); - - Vector allPossibleObstacles = myObstacleWorld.getAllObstaclesNear(subPath.getP1()); - - for (int k=0; k < allPossibleObstacles.size(); k++) { - Rectangle2D obstacle = allPossibleObstacles.get(k); - - // Calculate the intersection distance - Line2D line = getIntersectionLine( - subPath.getP1().getX(), - subPath.getP1().getY(), - subPath.getP2().getX(), - subPath.getP2().getY(), - obstacle - ); - - if (line != null) { - pathGain[i] += attenuationConstant * line.getP1().distance(line.getP2()); - break; - } - - } - - } - - // Add to total path length - pathLengths[i] += subPathLength; - } - - // Add FSPL from last rays (if FSPL on individual rays) - if (!getParameterBooleanValue("rt_fspl_on_total_length") && accumulatedStraightLength > 0) { - pathGain[i] += getFSPL(accumulatedStraightLength); - } - - // Free space path loss on total path length? - if (getParameterBooleanValue("rt_fspl_on_total_length")) { - pathGain[i] += getFSPL(pathLengths[i]); - } - - if (bestSignalNr < 0 || pathGain[i] > bestSignalPathLoss) { - bestSignalNr = i; - bestSignalPathLoss = pathGain[i]; - } - } - - // - Calculate total path loss (using simple Rician) - - double[] pathModdedLengths = new double[allPaths.size()]; - double delaySpread = 0; - double delaySpreadRMS = 0; - double wavelength = getParameterDoubleValue("wavelength"); - double totalPathGain = 0; - double delaySpreadTotalWeight = 0; - double speedOfLight = 300; // Approximate value (m/us) - for (int i=0; i < pathModdedLengths.length; i++) { - // Ignore insignificant interfering signals - if (pathGain[i] > pathGain[bestSignalNr] - 30) { - double pathLengthDiff = Math.abs(pathLengths[i] - pathLengths[bestSignalNr]); - - // Update delay spread TODO Now considering best signal, should be first or mean? - if (pathLengthDiff > delaySpread) - delaySpread = pathLengthDiff; - - - // Update root-mean-square delay spread TODO Now considering best signal time, should be mean delay? - delaySpreadTotalWeight += pathGain[i]*pathGain[i]; - double rmsDelaySpreadComponent = pathLengthDiff/speedOfLight; - rmsDelaySpreadComponent *= rmsDelaySpreadComponent * pathGain[i]*pathGain[i]; - delaySpreadRMS += rmsDelaySpreadComponent; - - // OK since cosinus is even function - pathModdedLengths[i] = pathLengthDiff % wavelength; - - // Using Rician fading approach, TODO Only one best signal considered - combine these? (need two limits) - totalPathGain += Math.pow(10, pathGain[i]/10.0)*Math.cos(2*Math.PI * pathModdedLengths[i]/wavelength); - if (inLoggingMode) { - logger.info("Adding ray path with gain " + pathGain[i] + " and phase " + (2*Math.PI * pathModdedLengths[i]/wavelength)); - } - } else if (inLoggingMode) { - pathModdedLengths[i] = (pathLengths[i] - pathLengths[bestSignalNr]) % wavelength; - logger.info("Not adding ray path with gain " + pathGain[i] + " and phase " + (2*Math.PI * pathModdedLengths[i]/wavelength)); - } - - } - - // Calculate resulting RMS delay spread - delaySpread /= speedOfLight; - delaySpreadRMS /= delaySpreadTotalWeight; - - - // Convert back to dB - totalPathGain = 10*Math.log10(Math.abs(totalPathGain)); - - if (inLoggingMode) { - logger.info("Total path gain:\t" + totalPathGain); - logger.info("Delay spread:\t" + delaySpread); - logger.info("RMS Delay spread:\t" + delaySpreadRMS); - } - - // - Calculate received power - - // Using formula (dB) - // Received power = Output power + System gain + Transmitter gain + Path Loss + Receiver gain - // TODO Update formulas - Random random = new Random(); - double outputPower = getParameterDoubleValue("tx_power"); - double systemGain = getParameterDoubleValue("system_gain_mean"); - if (getParameterBooleanValue("apply_random")) { - systemGain += Math.sqrt(getParameterDoubleValue("system_gain_var")) * random.nextGaussian(); - } else { - accumulatedVariance += getParameterDoubleValue("system_gain_var"); - } - double transmitterGain = getParameterDoubleValue("tx_antenna_gain"); // TODO Should depend on angle - - double receivedPower = outputPower + systemGain + transmitterGain + totalPathGain; - if (inLoggingMode) { - logger.info("Resulting received signal strength:\t" + receivedPower + " (" + accumulatedVariance + ")"); - } - - if (dataType == TransmissionData.DELAY_SPREAD || dataType == TransmissionData.DELAY_SPREAD_RMS) - return new double[] {delaySpread, delaySpreadRMS}; - - return new double[] {receivedPower, accumulatedVariance}; - } - - /** - * Returns all rays from given source to given destination if a transmission - * were to be made. The resulting rays depend on the current settings and may - * include rays through obstacles, reflected rays or scattered rays. - * - * @param sourceX Source position X - * @param sourceY Source position Y - * @param destX Destination position X - * @param destY Destination position Y - * @return All resulting rays of a simulated transmission from source to destination - */ - public Vector getRaysOfTransmission(double sourceX, double sourceY, double destX, double destY) { - - // Reset current rays vector - inLoggingMode = true; - savedRays = new Vector(); - - // Calculate rays, ignore power - getProbability(sourceX, sourceY, destX, destY, -Double.MAX_VALUE); - - inLoggingMode = false; - - return savedRays; - } - - /** - * Calculates and returns the signal to noise ratio (dB) of a signal sent from - * the given source position to the given destination position as a random - * variable. This method uses current parameters such as transmitted power, - * obstacles, overall system loss etc. - * - * @param sourceX - * Source position X - * @param sourceY - * Source position Y - * @param destX - * Destination position X - * @param destY - * Destination position Y - * @return Received SNR (dB) random variable. The first value is the random - * variable mean, and the second is the variance. The third value is the received signal strength which may be used in comparison with interference etc. - */ - public double[] getSINR(double sourceX, double sourceY, double destX, double destY, double interference) { - - // Calculate received signal strength - double[] signalStrength = getReceivedSignalStrength(sourceX, sourceY, destX, destY); - - double[] snrData = - new double[] { signalStrength[0], signalStrength[1], signalStrength[0] }; - - // Add antenna gain TODO Should depend on angle - snrData[0] += getParameterDoubleValue("rx_antenna_gain"); - - double noiseVariance = getParameterDoubleValue("bg_noise_var"); - double noiseMean = getParameterDoubleValue("bg_noise_mean"); - - if (interference > noiseMean) - noiseMean = interference; - - if (getParameterBooleanValue("apply_random")) { - noiseMean += Math.sqrt(noiseVariance) * random.nextGaussian(); - noiseVariance = 0; - } - - // Applying noise to calculate SNR - snrData[0] -= noiseMean; - snrData[1] += noiseVariance; - - if (inLoggingMode) { - logger.info("SNR at receiver:\t" + snrData[0] + " (" + snrData[1] + ")"); - } - return snrData; - } - - - /** - * Calculates and returns probability that a receiver at given destination receives a packet from a transmitter at given source. - * This method uses current parameters such as transmitted power, - * obstacles, overall system loss, packet size etc. TODO Packet size?! TODO Interfering signal strength - * - * @param sourceX - * Source position X - * @param sourceY - * Source position Y - * @param destX - * Destination position X - * @param destY - * Destination position Y - * @param interference - * Current interference at destination (dBm) - * @return [Probability of reception, signal strength at destination] - */ - public double[] getProbability(double sourceX, double sourceY, double destX, double destY, double interference) { - double[] snrData = getSINR(sourceX, sourceY, destX, destY, interference); - double snrMean = snrData[0]; - double snrVariance = snrData[1]; - double signalStrength = snrData[2]; - double threshold = getParameterDoubleValue("snr_threshold"); - double rxSensitivity = getParameterDoubleValue("rx_sensitivity"); - - // Check signal strength against receiver sensitivity and interference - if (rxSensitivity > signalStrength - snrMean && threshold < rxSensitivity + snrMean - signalStrength) { - if (inLoggingMode) { - logger.info("Signal to low for receiver sensitivity, increasing threshold"); - } - - // Keeping snr variance but increasing theshold to sensitivity - threshold = rxSensitivity + snrMean - signalStrength; - } - - // If not random varianble, probability is either 1 or 0 - if (snrVariance == 0) - return new double[] { - threshold - snrMean > 0 ? 0:1, signalStrength - }; - double snrStdDev = Math.sqrt(snrVariance); - - - // "Missing" signal strength in order to receive packet is probability that - // random variable with mean snrMean and standard deviance snrStdDev is above - // current threshold. - - // (Using error algorithm method, much faster than taylor approximation!) - double probReception = 1 - GaussianWrapper.cdfErrorAlgo( - threshold, snrMean, snrStdDev); - - if (inLoggingMode) { - logger.info("Probability of reception: " + probReception); - } - - // Returns probabilities - return new double[] { probReception, signalStrength }; - } - - /** - * Calculates and returns root-mean-square delay spread when given destination receives a packet from a transmitter at given source. - * This method uses current parameters such as transmitted power, - * obstacles, overall system loss, packet size etc. TODO Packet size?! - * - * @param sourceX - * Source position X - * @param sourceY - * Source position Y - * @param destX - * Destination position X - * @param destY - * Destination position Y - * @return RMS delay spread - */ - public double getRMSDelaySpread(double sourceX, double sourceY, double destX, double destY) { - return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.DELAY_SPREAD)[1]; - } - - /** - * Returns XML elements representing the current configuration. - * - * @see #setConfigXML(Collection) - * @return XML element collection - */ - public Collection getConfigXML() { - Vector config = new Vector(); - Element element; - - Enumeration paramEnum = parameters.keys(); - while (paramEnum.hasMoreElements()) { - String name = (String) paramEnum.nextElement(); - element = new Element(name); - element.setText(parameters.get(name).toString()); - config.add(element); - } - - element = new Element("obstacles"); - element.addContent(myObstacleWorld.getConfigXML()); - config.add(element); - - return config; - } - - /** - * Sets the configuration depending on the given XML elements. - * - * @see #getConfigXML() - * @param configXML - * Config XML elements - * @return True if config was set successfully, false otherwise - */ - public boolean setConfigXML(Collection configXML) { - for (Element element : configXML) { - if (element.getName().equals("obstacles")) { - myObstacleWorld = new ObstacleWorld(); - myObstacleWorld.setConfigXML(element.getChildren()); - } else { - // Assuming parameter value - - // Fetch current class before applying saved value - Object obj = parameters.get(element.getName()); - Class paramClass = obj.getClass(); - - if (paramClass == Double.class) { - parameters.put(element.getName(), new Double(Double.parseDouble(element.getText()))); - } else if (paramClass == Boolean.class) { - parameters.put(element.getName(), Boolean.parseBoolean(element.getText())); - } else if (paramClass == Integer.class) { - parameters.put(element.getName(), Integer.parseInt(element.getText())); - } else { - logger.fatal("Unsupported class type: " + paramClass); - } - } - } - needToPrecalculateFSPL = true; - needToPrecalculateOutputPower = true; - settingsObservable.notifySettingsChanged(); - return true; - } - -} - - diff --git a/tools/cooja/apps/arm/java/se/sics/arm/FormulaViewer.java b/tools/cooja/apps/arm/java/se/sics/arm/FormulaViewer.java deleted file mode 100644 index e798bd825..000000000 --- a/tools/cooja/apps/arm/java/se/sics/arm/FormulaViewer.java +++ /dev/null @@ -1,583 +0,0 @@ -package se.sics.arm; - -import java.awt.*; -import java.awt.event.*; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.text.NumberFormat; -import java.util.*; -import javax.swing.*; -import org.apache.log4j.Logger; -import org.jdom.Element; - -import se.sics.cooja.*; - -/** - * This plugin allows a user to reconfigure current radio channel parameters. - * - * @author Fredrik Osterlind - */ -@ClassDescription("ARM - Formula Viewer") -@VisPluginType(VisPluginType.SIM_PLUGIN) -public class FormulaViewer extends se.sics.cooja.VisPlugin { - private static final long serialVersionUID = 1L; - private static Logger logger = Logger.getLogger(FormulaViewer.class); - - private Simulation currentSimulation; - private AdvancedRadioMedium currentRadioMedium; - private ChannelModel currentChannelModel; - - private static Dimension labelDimension = new Dimension(240, 20); - private static NumberFormat doubleFormat = NumberFormat.getNumberInstance(); - private static NumberFormat integerFormat = NumberFormat.getIntegerInstance(); - - private Vector allIntegerParameters = new Vector(); - private Vector allDoubleParameters = new Vector(); - private Vector allBooleanParameters = new Vector(); - - private JPanel areaGeneral; - private JPanel areaTransmitter; - private JPanel areaReceiver; - private JPanel areaRayTracer; - private JPanel areaShadowing; - - /** - * Creates a new formula viewer. - * - * @param simulationToVisualize Simulation which holds the ARM channel model. - */ - public FormulaViewer(Simulation simulationToVisualize) { - super("Advanced Radio Medium - Formula Viewer"); - - currentSimulation = simulationToVisualize; - currentRadioMedium = (AdvancedRadioMedium) currentSimulation.getRadioMedium(); - currentChannelModel = currentRadioMedium.getChannelModel(); - - // -- Create and add GUI components -- - JPanel allComponents = new JPanel(); - allComponents.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - allComponents.setLayout(new BoxLayout(allComponents, BoxLayout.Y_AXIS)); - - JScrollPane scrollPane = new JScrollPane(allComponents); - scrollPane.setPreferredSize(new Dimension(500,400)); - scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); - scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - setContentPane(scrollPane); - - JPanel collapsableArea; - - // General parameters - collapsableArea = createCollapsableArea("General parameters", allComponents); - areaGeneral = collapsableArea; - - addBooleanParameter( - "apply_random", - currentChannelModel.getParameterDescription("apply_random"), - collapsableArea, - currentChannelModel.getParameterBooleanValue("apply_random") - ); - - addDoubleParameter( - "snr_threshold", - currentChannelModel.getParameterDescription("snr_threshold"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("snr_threshold") - ); - - addDoubleParameter( - "bg_noise_mean", - currentChannelModel.getParameterDescription("bg_noise_mean"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("bg_noise_mean") - ); - - addDoubleParameter( - "bg_noise_var", - currentChannelModel.getParameterDescription("bg_noise_var"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("bg_noise_var") - ); - - addDoubleParameter( - "system_gain_mean", - currentChannelModel.getParameterDescription("system_gain_mean"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("system_gain_mean") - ); - - addDoubleParameter( - "system_gain_var", - currentChannelModel.getParameterDescription("system_gain_var"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("system_gain_var") - ); - - addDoubleParameter( - "wavelength", - currentChannelModel.getParameterDescription("wavelength"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("wavelength") - ); - - // Transmitter parameters - collapsableArea = createCollapsableArea("Transmitter parameters", allComponents); - areaTransmitter = collapsableArea; - - addDoubleParameter( - "tx_power", - currentChannelModel.getParameterDescription("tx_power"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("tx_power") - ); - - addDoubleParameter( - "tx_antenna_gain", - currentChannelModel.getParameterDescription("tx_antenna_gain"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("tx_antenna_gain") - ); - - // Receiver parameters - collapsableArea = createCollapsableArea("Receiver parameters", allComponents); - areaReceiver = collapsableArea; - - addDoubleParameter( - "rx_sensitivity", - currentChannelModel.getParameterDescription("rx_sensitivity"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("rx_sensitivity") - ); - - addDoubleParameter( - "rx_antenna_gain", - currentChannelModel.getParameterDescription("rx_antenna_gain"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("rx_antenna_gain") - ); - - // Ray Tracer parameters - collapsableArea = createCollapsableArea("Ray Tracer parameters", allComponents); - areaRayTracer = collapsableArea; - - addBooleanParameter( - "rt_disallow_direct_path", - currentChannelModel.getParameterDescription("rt_disallow_direct_path"), - collapsableArea, - currentChannelModel.getParameterBooleanValue("rt_disallow_direct_path") - ); - - addBooleanParameter( - "rt_ignore_non_direct", - currentChannelModel.getParameterDescription("rt_ignore_non_direct"), - collapsableArea, - currentChannelModel.getParameterBooleanValue("rt_ignore_non_direct") - ); - - addBooleanParameter( - "rt_fspl_on_total_length", - currentChannelModel.getParameterDescription("rt_fspl_on_total_length"), - collapsableArea, - currentChannelModel.getParameterBooleanValue("rt_fspl_on_total_length") - ); - - addIntegerParameter( - "rt_max_rays", - currentChannelModel.getParameterDescription("rt_max_rays"), - collapsableArea, - currentChannelModel.getParameterIntegerValue("rt_max_rays") - ); - - addIntegerParameter( - "rt_max_refractions", - currentChannelModel.getParameterDescription("rt_max_refractions"), - collapsableArea, - currentChannelModel.getParameterIntegerValue("rt_max_refractions") - ); - - addIntegerParameter( - "rt_max_reflections", - currentChannelModel.getParameterDescription("rt_max_reflections"), - collapsableArea, - currentChannelModel.getParameterIntegerValue("rt_max_reflections") - ); - - addIntegerParameter( - "rt_max_diffractions", - currentChannelModel.getParameterDescription("rt_max_diffractions"), - collapsableArea, - currentChannelModel.getParameterIntegerValue("rt_max_diffractions") - ); - -/* addBooleanParameter( - "rt_use_scattering", - currentChannelModel.getParameterDescription("rt_use_scattering"), - collapsableArea, - currentChannelModel.getParameterBooleanValue("rt_use_scattering") - ); -*/ - addDoubleParameter( - "rt_refrac_coefficient", - currentChannelModel.getParameterDescription("rt_refrac_coefficient"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("rt_refrac_coefficient") - ); - - addDoubleParameter( - "rt_reflec_coefficient", - currentChannelModel.getParameterDescription("rt_reflec_coefficient"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("rt_reflec_coefficient") - ); - - addDoubleParameter( - "rt_diffr_coefficient", - currentChannelModel.getParameterDescription("rt_diffr_coefficient"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("rt_diffr_coefficient") - ); - -/* addDoubleParameter( - "rt_scatt_coefficient", - currentChannelModel.getParameterDescription("rt_scatt_coefficient"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("rt_scatt_coefficient") - ); -*/ - // Shadowing parameters - collapsableArea = createCollapsableArea("Shadowing parameters", allComponents); - areaShadowing = collapsableArea; - - addDoubleParameter( - "obstacle_attenuation", - currentChannelModel.getParameterDescription("obstacle_attenuation"), - collapsableArea, - currentChannelModel.getParameterDoubleValue("obstacle_attenuation") - ); - - - - // Add channel model observer responsible to keep all GUI components synched - currentChannelModel.addSettingsObserver(channelModelSettingsObserver); - - // Set initial size etc. - pack(); - setVisible(true); - - // Tries to select this plugin - try { - setSelected(true); - } catch (java.beans.PropertyVetoException e) { - // Could not select - } - - } - - /** - * Creates a new collapsable area which may be used for holding model parameters. - * @param title Title of area - * @param contentPane Where this area should be added - * @return New empty collapsable area - */ - private JPanel createCollapsableArea(String title, Container contentPane) { - // Create panels - JPanel holdingPanel = new JPanel() { - public Dimension getMaximumSize() { - return new Dimension(super.getMaximumSize().width, getPreferredSize().height); - } - }; - holdingPanel.setLayout(new BoxLayout(holdingPanel, BoxLayout.Y_AXIS)); - - final JPanel collapsableArea = new JPanel() { - public Dimension getMaximumSize() { - return new Dimension(super.getMaximumSize().width, getPreferredSize().height); - } - }; - collapsableArea.setLayout(new BoxLayout(collapsableArea, BoxLayout.Y_AXIS)); - collapsableArea.setVisible(false); - - JPanel titlePanel = new JPanel(new BorderLayout()) { - public Dimension getMaximumSize() { - return new Dimension(super.getMaximumSize().width, getPreferredSize().height); - } - }; - - titlePanel.add(BorderLayout.WEST, new JLabel(title)); - JCheckBox collapseCheckBox = new JCheckBox("show settings", false); - collapseCheckBox.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (((JCheckBox) e.getSource()).isSelected()) - collapsableArea.setVisible(true); - else - collapsableArea.setVisible(false); - } - }); - collapsableArea.putClientProperty("my_checkbox", collapseCheckBox); - - titlePanel.add(BorderLayout.EAST, collapseCheckBox); - - collapsableArea.setBorder( - BorderFactory.createLineBorder(Color.LIGHT_GRAY) - ); - collapsableArea.setAlignmentY(Component.TOP_ALIGNMENT); - - holdingPanel.add(titlePanel); - holdingPanel.add(collapsableArea); - - contentPane.add(holdingPanel); - return collapsableArea; - } - - /** - * Creates and adds a panel with a label and a - * text field which accepts doubles. - * - * @param id Identifier of new parameter - * @param description Description of new parameter - * @param contentPane Where to add created panel - * @param initialValue Initial value - * @return Text field in created panel - */ - private JFormattedTextField addDoubleParameter(String id, String description, Container contentPane, double initialValue) { - JPanel panel = new JPanel(); - JLabel label; - JFormattedTextField textField; - - panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); - panel.setAlignmentY(Component.TOP_ALIGNMENT); - panel.add(Box.createHorizontalStrut(10)); - panel.add(label = new JLabel(description)); - label.setPreferredSize(labelDimension); - panel.add(Box.createHorizontalGlue()); - panel.add(textField = new JFormattedTextField(doubleFormat)); - textField.setValue(new Double(initialValue)); - textField.setColumns(4); - textField.putClientProperty("id", id); - textField.addPropertyChangeListener("value", new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent e) { - Object sourceObject = e.getSource(); - Double newValue = ((Number) e.getNewValue()).doubleValue(); - String id = (String) ((JFormattedTextField) sourceObject).getClientProperty("id"); - currentChannelModel.setParameterValue(id, newValue); - } - }); - allDoubleParameters.add(textField); - - contentPane.add(panel); - - return textField; - } - - /** - * Creates and adds a panel with a label and a - * text field which accepts integers. - * - * @param id Identifier of new parameter - * @param description Description of new parameter - * @param contentPane Where to add created panel - * @param initialValue Initial value - * @return Text field in created panel - */ - private JFormattedTextField addIntegerParameter(String id, String description, Container contentPane, int initialValue) { - JPanel panel = new JPanel(); - JLabel label; - JFormattedTextField textField; - - panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); - panel.setAlignmentY(Component.TOP_ALIGNMENT); - panel.add(Box.createHorizontalStrut(10)); - panel.add(label = new JLabel(description)); - label.setPreferredSize(labelDimension); - panel.add(Box.createHorizontalGlue()); - panel.add(textField = new JFormattedTextField(integerFormat)); - textField.setValue(new Double(initialValue)); - textField.setColumns(4); - textField.putClientProperty("id", id); - textField.addPropertyChangeListener("value", new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent e) { - Object sourceObject = e.getSource(); - Integer newValue = ((Number) e.getNewValue()).intValue(); - String id = (String) ((JFormattedTextField) sourceObject).getClientProperty("id"); - currentChannelModel.setParameterValue(id, newValue); - } - }); - - allIntegerParameters.add(textField); - - contentPane.add(panel); - - return textField; - } - - /** - * Creates and adds a panel with a label and a - * boolean checkbox. - * - * @param id Identifier of new parameter - * @param description Description of new parameter - * @param contentPane Where to add created panel - * @param initialValue Initial value - * @return Checkbox in created panel - */ - private JCheckBox addBooleanParameter(String id, String description, Container contentPane, boolean initialValue) { - JPanel panel = new JPanel(); - JLabel label; - JCheckBox checkBox; - - panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); - panel.setAlignmentY(Component.TOP_ALIGNMENT); - panel.add(Box.createHorizontalStrut(10)); - panel.add(label = new JLabel(description)); - label.setPreferredSize(labelDimension); - panel.add(Box.createHorizontalGlue()); - panel.add(checkBox = new JCheckBox()); - checkBox.setSelected(initialValue); - checkBox.putClientProperty("id", id); - checkBox.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - JCheckBox source = (JCheckBox) e.getSource(); - currentChannelModel.setParameterValue( - (String) source.getClientProperty("id"), - new Boolean(source.isSelected()) - ); - } - }); - - allBooleanParameters.add(checkBox); - - contentPane.add(panel); - - return checkBox; - } - - /** - * Creates and adds a panel with a description label. - * - * @param description Description of new parameter - * @param contentPane Where to add created panel - * @return Created label - */ - private JLabel addLabelParameter(String description, Container contentPane) { - JPanel panel = new JPanel(); - JLabel label; - - panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); - panel.setAlignmentY(Component.TOP_ALIGNMENT); - panel.add(Box.createHorizontalStrut(10)); - panel.add(label = new JLabel(description)); - label.setPreferredSize(labelDimension); - panel.add(Box.createHorizontalGlue()); - - contentPane.add(panel); - - return label; - } - - /** - * Listens to settings changes in the channel model. - * If it changes, all GUI parameters are updated accordingly. - */ - private Observer channelModelSettingsObserver = new Observer() { - public void update(Observable obs, Object obj) { - // Update all integers - for (int i=0; i < allIntegerParameters.size(); i++) { - JFormattedTextField textField = (JFormattedTextField) allIntegerParameters.get(i); - String id = (String) textField.getClientProperty("id"); - textField.setValue(currentChannelModel.getParameterValue(id)); - } - - // Update all doubles - for (int i=0; i < allDoubleParameters.size(); i++) { - JFormattedTextField textField = (JFormattedTextField) allDoubleParameters.get(i); - String id = (String) textField.getClientProperty("id"); - textField.setValue(currentChannelModel.getParameterValue(id)); - } - - // Update all booleans - for (int i=0; i < allBooleanParameters.size(); i++) { - JCheckBox checkBox = (JCheckBox) allBooleanParameters.get(i); - String id = (String) checkBox.getClientProperty("id"); - checkBox.setSelected(currentChannelModel.getParameterBooleanValue(id)); - } - - repaint(); - } - }; - - public void closePlugin() { - // Remove the channel model observer - if (currentChannelModel != null && channelModelSettingsObserver != null) { - currentChannelModel.deleteSettingsObserver(channelModelSettingsObserver); - } else { - logger.fatal("Can't remove channel model observer: " + channelModelSettingsObserver); - } - } - - /** - * Returns XML elements representing the current configuration. - * - * @see #setConfigXML(Collection) - * @return XML element collection - */ - public Collection getConfigXML() { - Vector config = new Vector(); - Element element; - - element = new Element("show_general"); - element.setText(Boolean.toString(areaGeneral.isVisible())); - config.add(element); - element = new Element("show_transmitter"); - element.setText(Boolean.toString(areaTransmitter.isVisible())); - config.add(element); - element = new Element("show_receiver"); - element.setText(Boolean.toString(areaReceiver.isVisible())); - config.add(element); - element = new Element("show_raytracer"); - element.setText(Boolean.toString(areaRayTracer.isVisible())); - config.add(element); - element = new Element("show_shadowing"); - element.setText(Boolean.toString(areaShadowing.isVisible())); - config.add(element); - return config; - } - - /** - * Sets the configuration depending on the given XML elements. - * - * @see #getConfigXML() - * @param configXML - * Config XML elements - * @return True if config was set successfully, false otherwise - */ - public boolean setConfigXML(Collection configXML) { - for (Element element : configXML) { - if (element.getName().equals("show_general")) { - JCheckBox checkBox = (JCheckBox) areaGeneral.getClientProperty("my_checkbox"); - checkBox.setSelected(Boolean.parseBoolean(element.getText())); - checkBox.getActionListeners()[0].actionPerformed(new ActionEvent(checkBox, - ActionEvent.ACTION_PERFORMED, "")); - } else if (element.getName().equals("show_transmitter")) { - JCheckBox checkBox = (JCheckBox) areaTransmitter.getClientProperty("my_checkbox"); - checkBox.setSelected(Boolean.parseBoolean(element.getText())); - checkBox.getActionListeners()[0].actionPerformed(new ActionEvent(checkBox, - ActionEvent.ACTION_PERFORMED, "")); - } else if (element.getName().equals("show_receiver")) { - JCheckBox checkBox = (JCheckBox) areaReceiver.getClientProperty("my_checkbox"); - checkBox.setSelected(Boolean.parseBoolean(element.getText())); - checkBox.getActionListeners()[0].actionPerformed(new ActionEvent(checkBox, - ActionEvent.ACTION_PERFORMED, "")); - } else if (element.getName().equals("show_raytracer")) { - JCheckBox checkBox = (JCheckBox) areaRayTracer.getClientProperty("my_checkbox"); - checkBox.setSelected(Boolean.parseBoolean(element.getText())); - checkBox.getActionListeners()[0].actionPerformed(new ActionEvent(checkBox, - ActionEvent.ACTION_PERFORMED, "")); - } else if (element.getName().equals("show_shadowing")) { - JCheckBox checkBox = (JCheckBox) areaShadowing.getClientProperty("my_checkbox"); - checkBox.setSelected(Boolean.parseBoolean(element.getText())); - checkBox.getActionListeners()[0].actionPerformed(new ActionEvent(checkBox, - ActionEvent.ACTION_PERFORMED, "")); - } - } - return true; - } - -} diff --git a/tools/cooja/apps/arm/java/se/sics/arm/Interval.java b/tools/cooja/apps/arm/java/se/sics/arm/Interval.java deleted file mode 100644 index 0af30610b..000000000 --- a/tools/cooja/apps/arm/java/se/sics/arm/Interval.java +++ /dev/null @@ -1,205 +0,0 @@ -package se.sics.arm; - -import java.util.Vector; -import org.apache.log4j.Logger; - -/** - * This class represents a interval. Some operations on these intervals exist, - * such as intersecting a interval with another and subtracting an interval from - * another. - * - * @author Fredrik Osterlind - */ -class Interval { - private static Logger logger = Logger.getLogger(Interval.class); - - private double lowValue; - private double highValue; - - /** - * Creates a new double interval. - * The given low value must be lower than the given high value. - * - * @param lowValue Low interval border (< End interval border) - * @param highValue High interval border - */ - public Interval(double lowValue, double highValue) { - this.lowValue = Math.min(lowValue, highValue); - this.highValue = highValue; - } - - /** - * Set new values of interval - * - * @param newLow New low value - * @param newHigh New high value - */ - public void setInterval(double newLow, double newHigh) { - lowValue = newLow; - highValue = newHigh; - } - - /** - * @return Low border value - */ - public double getLow() { - return lowValue; - } - - /** - * @return High border value - */ - public double getHigh() { - return highValue; - } - - /** - * @return Size of interval - */ - public double getSize() { - return highValue - lowValue; - } - - /** - * Returns the intersection between this interval and the given - * interval or null if no intersection exists. - * - * @param interval Other interval - * @return Intersection interval - */ - public Interval intersectWith(Interval interval) { - // Given interval higher than this interval - if (highValue <= interval.getLow()) - return null; - - // Given interval lower than this interval - if (lowValue >= interval.getHigh()) - return null; - - // Given interval covers this interval - if (lowValue >= interval.getLow() && - highValue <= interval.getHigh()) - return this; - - // Given interval inside this interval - if (lowValue <= interval.getLow() && - highValue >= interval.getHigh()) - return interval; - - // Given interval overlaps lower part of this interval - if (lowValue >= interval.getLow() && - highValue >= interval.getHigh()) - return new Interval(lowValue, interval.getHigh()); - - // Given interval overlaps upper part of this interval - if (lowValue <= interval.getLow() && - highValue <= interval.getHigh()) - return new Interval(interval.getLow(), highValue); - - logger.fatal("DoubleInterval.intersectWithInterval(), error!"); - return null; - } - - /** - * Checks if the given interval is a subset of this interval. - * - * @param interval Other interval - * @return True if this interval contains the given interval - */ - public boolean contains(Interval interval) { - return getLow() <= interval.getLow() && getHigh() >= interval.getHigh(); - } - - /** - * Returns new intervals consisting of this interval with the given interval removed. - * These can either be null (if entire interval was removed), - * one interval (if upper or lower part, or nothing was removed) or two intervals - * (if middle part of interval was removed). - * - * @param interval Other interval - * @return New intervals - */ - public Vector subtract(Interval interval) { - Vector returnIntervals = new Vector(); - - // Given interval higher than this interval - if (highValue <= interval.getLow()) { - returnIntervals.add(this); - return returnIntervals; - } - - // Given interval lower than this interval - if (lowValue >= interval.getHigh()) { - returnIntervals.add(this); - return returnIntervals; - } - - // Given interval covers this interval - if (lowValue >= interval.getLow() && - highValue <= interval.getHigh()) { - return null; - } - - // Given interval inside this interval - if (lowValue <= interval.getLow() && - highValue >= interval.getHigh()) { - returnIntervals.add(new Interval(lowValue, interval.getLow())); - returnIntervals.add(new Interval(interval.getHigh(), highValue)); - return returnIntervals; - } - - // Given interval overlaps lower part of this interval - if (lowValue >= interval.getLow() && - highValue >= interval.getHigh()) { - returnIntervals.add(new Interval(interval.getHigh(), highValue)); - return returnIntervals; - } - - // Given interval overlaps upper part of this interval - if (lowValue <= interval.getLow() && - highValue <= interval.getHigh()) { - returnIntervals.add(new Interval(lowValue, interval.getLow())); - return returnIntervals; - } - - logger.fatal("DoubleInterval.subtractInterval(), error!"); - return null; - } - - /** - * Subtracts given interval from all intervals in given vector. - * This method never returns null (but empty vectors). - * - * @param initialIntervals Initial intervals - * @param interval Interval to subtract - * @return New intervals - */ - static public Vector subtract(Vector initialIntervals, Interval interval) { - Vector newIntervals = new Vector(); - for (int i=0; i < initialIntervals.size(); i++) { - Vector tempIntervals = initialIntervals.get(i).subtract(interval); - if (tempIntervals != null) - newIntervals.addAll(tempIntervals); - } - return newIntervals; - } - - /** - * @return True if interval does not have a length. - */ - public boolean isEmpty() { - if (highValue <= lowValue) - return true; - return false; - } - - public String toString() { - if (isEmpty()) - return "Double interval: (null)"; - else - return "Double interval: " + - getLow() + - " -> " + - getHigh(); - } -} \ No newline at end of file diff --git a/tools/cooja/apps/arm/java/se/sics/arm/ObstacleWorld.java b/tools/cooja/apps/arm/java/se/sics/arm/ObstacleWorld.java deleted file mode 100644 index 3a0d288f4..000000000 --- a/tools/cooja/apps/arm/java/se/sics/arm/ObstacleWorld.java +++ /dev/null @@ -1,621 +0,0 @@ -package se.sics.arm; - -import java.awt.Point; -import java.awt.geom.*; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Vector; -import org.apache.log4j.Logger; -import org.jdom.Element; - -/** - * This class represents an area with obstacles. - * Obstacles may only be of rectangular shape. - * - * @author Fredrik Osterlind - */ -class ObstacleWorld { - private static Logger logger = Logger.getLogger(ObstacleWorld.class); - - // All registered obstacles - private Vector allObstacles = null; - - // All registered obstacles, with spatial information - private int spatialResolution = 10; - private Vector[][] allObstaclesSpatial = new Vector[spatialResolution][spatialResolution]; - private boolean obstaclesOrganized = false; - - // Outer bounds of all obstacles - private Rectangle2D outerBounds = null; - - - /** - * Creates a new obstacle world without any obstacles. - */ - public ObstacleWorld() { - // No obstacles present so far - allObstacles = new Vector(); - - for (int x=0; x < spatialResolution; x++) - for (int y=0; y < spatialResolution; y++) - allObstaclesSpatial[x][y] = new Vector(); - - outerBounds = new Rectangle2D.Double(0,0,0,0); - } - - /** - * @return The total number of registered obstacles - */ - public int getNrObstacles() { - return allObstacles.size(); - } - - /** - * This method can be used to find extreme coordinates of all obstacles. - * - * @return Outer bounds of all registered obstacles - */ - public Rectangle2D getOuterBounds() { - return outerBounds; - } - - /** - * Returns obstacle registered at given position. - * The coordinates of an obstacles should never - * be changed directly on an object returned by this method. - * - * @param i Obstacle position - * @return Obstacle at given position - */ - public Rectangle2D getObstacle(int i) { - return allObstacles.get(i); - } - - /** - * @return All registered obstacles - */ - public Vector getAllObstacles() { - return allObstacles; - } - - /** - * Returns at least all registered obstacles that contains given point. - * Note that obstacles close to but not containing the point may also - * be returned. - * - * @param center Center point - * @return All obstacles containing or near center - */ - public Vector getAllObstaclesNear(Point2D center) { - double boxWidth = outerBounds.getWidth() / (double) spatialResolution; - double boxHeight = outerBounds.getHeight() / (double) spatialResolution; - double areaStartX = outerBounds.getMinX(); - double areaStartY = outerBounds.getMinY(); - - double centerX = (center.getX() - areaStartX)/boxWidth; - double centerY = (center.getY() - areaStartY)/boxHeight; - - Vector allNearObstacles = new Vector(); - - Point pointToAdd = new Point((int) centerX, (int) centerY); - if (pointToAdd.x >= 0 && - pointToAdd.x < allObstaclesSpatial.length && - pointToAdd.y >= 0 && - pointToAdd.y < allObstaclesSpatial[0].length) - allNearObstacles.addAll(allObstaclesSpatial[pointToAdd.x][pointToAdd.y]); - - // Add borders if needed - boolean addedXBorder = false; - boolean addedYBorder = false; - if (Math.floor(centerX) == centerX) { - pointToAdd = new Point((int) centerX-1, (int) centerY); - if (pointToAdd.x >= 0 && - pointToAdd.x < allObstaclesSpatial.length && - pointToAdd.y >= 0 && - pointToAdd.y < allObstaclesSpatial[0].length) { - allNearObstacles.addAll(allObstaclesSpatial[pointToAdd.x][pointToAdd.y]); - addedXBorder = true; - } - } - - if (Math.floor(centerY) == centerY) { - pointToAdd = new Point((int) centerX, (int) centerY-1); - if (pointToAdd.x >= 0 && - pointToAdd.x < allObstaclesSpatial.length && - pointToAdd.y >= 0 && - pointToAdd.y < allObstaclesSpatial[0].length) { - allNearObstacles.addAll(allObstaclesSpatial[pointToAdd.x][pointToAdd.y]); - addedYBorder = true; - } - } - - if (addedXBorder && addedYBorder) { - pointToAdd = new Point((int) centerX-1, (int) centerY-1); - allNearObstacles.addAll(allObstaclesSpatial[pointToAdd.x][pointToAdd.y]); - } - - return allNearObstacles; - } - - /** - * Returns at least all registered obstacles inside the given angle - * interval when at the given center point. Note that obstacles partly or - * completely outside the interval may also be returned. - * All obstacles are preferably returned in order of distance from given - * center point, although this is not guaranteed. - * - * @param center Center point - * @param angleInterval Angle interval - * @return All obstacles in given angle interval - */ - public Vector getAllObstaclesInAngleInterval(Point2D center, AngleInterval angleInterval) { - Vector obstaclesToReturn = new Vector(); - if (!obstaclesOrganized) { - reorganizeSpatialObstacles(); - } - - double boxWidth = outerBounds.getWidth() / (double) spatialResolution; - double boxHeight = outerBounds.getHeight() / (double) spatialResolution; - double areaStartX = outerBounds.getMinX(); - double areaStartY = outerBounds.getMinY(); - - // Calculate which boxes to check (and in which order) - Point centerInArray = new Point( - (int) ((center.getX() - areaStartX)/boxWidth), - (int) ((center.getY() - areaStartY)/boxHeight) - ); - Vector pointsToCheck = new Vector(); - - int currentDistance = 0; - while (currentDistance < 2*spatialResolution) { - - if (currentDistance > 0) { - int currentX = centerInArray.x - currentDistance; - int currentY = centerInArray.y - currentDistance; - - // Step right - while (currentX < centerInArray.x + currentDistance) { - if (currentX >= 0 && - currentX < allObstaclesSpatial.length && - currentY >= 0 && - currentY < allObstaclesSpatial[0].length) - pointsToCheck.add(new Point(currentX, currentY)); - currentX++; - } - - // Step right - while (currentY < centerInArray.y + currentDistance) { - if (currentX >= 0 && - currentX < allObstaclesSpatial.length && - currentY >= 0 && - currentY < allObstaclesSpatial[0].length) - pointsToCheck.add(new Point(currentX, currentY)); - currentY++; - } - - // Step left - while (currentX > centerInArray.x - currentDistance) { - if (currentX >= 0 && - currentX < allObstaclesSpatial.length && - currentY >= 0 && - currentY < allObstaclesSpatial[0].length) - pointsToCheck.add(new Point(currentX, currentY)); - currentX--; - } - - // Step up - while (currentY > centerInArray.y - currentDistance) { - if (currentX >= 0 && - currentX < allObstaclesSpatial.length && - currentY >= 0 && - currentY < allObstaclesSpatial[0].length) - pointsToCheck.add(new Point(currentX, currentY)); - currentY--; - } - - } else { - if (centerInArray.x >= 0 && - centerInArray.x < allObstaclesSpatial.length && - centerInArray.y >= 0 && - centerInArray.y < allObstaclesSpatial[0].length) { - pointsToCheck.add(new Point(centerInArray.x, centerInArray.y)); - } - } - currentDistance++; - } - - for (int pointNr=0; pointNr < pointsToCheck.size(); pointNr++) { - // Check which obstacles should be in this box - boolean hit = false; - int x = pointsToCheck.get(pointNr).x; - int y = pointsToCheck.get(pointNr).y; - - // Test if we are inside test box - if (!hit) { - if (new Rectangle2D.Double( - areaStartX + x*boxWidth, - areaStartY + y*boxHeight, - boxWidth, - boxHeight).contains(center)) { - hit = true; - for (int i=0; i < allObstaclesSpatial[x][y].size(); i++) { - if (!obstaclesToReturn.contains(allObstaclesSpatial[x][y].get(i))) - obstaclesToReturn.add(allObstaclesSpatial[x][y].get(i)); - } - } - } - - // Test first diagonal - if (!hit) { - AngleInterval testInterval = AngleInterval.getAngleIntervalOfLine( - center, - new Line2D.Double( - areaStartX + x*boxWidth, - areaStartY + y*boxHeight, - areaStartX + (x+1)*boxWidth, - areaStartY + (y+1)*boxHeight) - ); - if (testInterval.intersects(angleInterval)) { - hit = true; - for (int i=0; i < allObstaclesSpatial[x][y].size(); i++) { - if (!obstaclesToReturn.contains(allObstaclesSpatial[x][y].get(i))) - obstaclesToReturn.add(allObstaclesSpatial[x][y].get(i)); - } - } - } - - // Test second diagonal - if (!hit) { - AngleInterval testInterval = AngleInterval.getAngleIntervalOfLine( - center, - new Line2D.Double( - areaStartX + x*boxWidth, - areaStartY + (y+1)*boxHeight, - areaStartX + (x+1)*boxWidth, - areaStartY + y*boxHeight) - ); - if (testInterval.intersects(angleInterval)) { - hit = true; - for (int i=0; i < allObstaclesSpatial[x][y].size(); i++) { - if (!obstaclesToReturn.contains(allObstaclesSpatial[x][y].get(i))) - obstaclesToReturn.add(allObstaclesSpatial[x][y].get(i)); - } - } - } - } - - return obstaclesToReturn; - } - - /** - * Removes all registered obstacles. - */ - public void removeAll() { - allObstacles.removeAllElements(); - for (int x=0; x < spatialResolution; x++) - for (int y=0; y < spatialResolution; y++) - allObstaclesSpatial[x][y].removeAllElements(); - - outerBounds = new Rectangle2D.Double(0,0,0,0); - } - - /** - * Returns true of given point is on a corner of - * any of the structures build from the obstacles. - * Internally this method checks how many of four point - * close to and located around given point (diagonally) are - * inside any obstacle. - * This method returns true if exactly one point is inside an obstacle. - * - * @param point Point to check - * @return True of point is on a corner, false otherwise - */ - public boolean pointIsNearCorner(Point2D point) { - double boxWidth = outerBounds.getWidth() / (double) spatialResolution; - double boxHeight = outerBounds.getHeight() / (double) spatialResolution; - double areaStartX = outerBounds.getMinX(); - double areaStartY = outerBounds.getMinY(); - - // Which obstacles should be checked - Point centerInArray = new Point( - (int) ((point.getX() - areaStartX)/boxWidth), - (int) ((point.getY() - areaStartY)/boxHeight) - ); - Vector allObstaclesToCheck = null; - if (centerInArray.x < 0) - centerInArray.x = 0; - if (centerInArray.x >= spatialResolution) - centerInArray.x = spatialResolution-1; - if (centerInArray.y < 0) - centerInArray.y = 0; - if (centerInArray.y >= spatialResolution) - centerInArray.y = spatialResolution-1; - - allObstaclesToCheck = allObstaclesSpatial[centerInArray.x][centerInArray.y]; - - if (allObstaclesToCheck.size() == 0) { - return false; - } - - // Create the four point to check - double deltaDistance = 0.01; // 1 cm TODO Change this? - Point2D point1 = new Point2D.Double(point.getX() - deltaDistance, point.getY() - deltaDistance); - Point2D point2 = new Point2D.Double(point.getX() - deltaDistance, point.getY() + deltaDistance); - Point2D point3 = new Point2D.Double(point.getX() + deltaDistance, point.getY() - deltaDistance); - Point2D point4 = new Point2D.Double(point.getX() + deltaDistance, point.getY() + deltaDistance); - - int containedPoints = 0; - Enumeration allObstaclesToCheckEnum = allObstaclesToCheck.elements(); - while (allObstaclesToCheckEnum.hasMoreElements()) { - Rectangle2D obstacleToCheck = allObstaclesToCheckEnum.nextElement(); - if (obstacleToCheck.contains(point1)) - containedPoints++; - if (obstacleToCheck.contains(point2)) - containedPoints++; - if (obstacleToCheck.contains(point3)) - containedPoints++; - if (obstacleToCheck.contains(point4)) - containedPoints++; - - // Abort if already to many contained points - if (containedPoints > 1) { - return false; - } - } - - return (containedPoints == 1); - } - - /** - * Checks if specified obstacle can be merged with any existing obstacle - * in order to reduce the total number of obstacles. And in that case a merge - * is performed and this method returns the new obstacle object. - * The checking is performed by looping through all existing obstacles and - * for each one comparing the union area of it and the given obstacle to the - * area sum of the two. And since obstacles are not allowed to overlap, if the - * union area is equal to the area sum, they can be merged. - * If a merge is performed, another may be made possible so this method - * should be looped until returning null. - * - * This method does not notify observers of changes made! - * - * @return New object of a merge was performed, null otherwise - */ - private Rectangle2D mergeObstacle(Rectangle2D mergeObstacle) { - double mergeObstacleArea = mergeObstacle.getWidth() * mergeObstacle.getHeight(); - double mergeObstacleTolerance = mergeObstacleArea * 0.01; // 1% - - // Loop through all existing obstacles (but ignore itself) - for (int i=0; i < getNrObstacles(); i++) { - Rectangle2D existingObstacle = getObstacle(i); - if (!existingObstacle.equals(mergeObstacle)) { - double existingObstacleArea = existingObstacle.getWidth() * existingObstacle.getHeight(); - Rectangle2D unionObstacle = existingObstacle.createUnion(mergeObstacle); - double unionArea = unionObstacle.getWidth() * unionObstacle.getHeight(); - - // Fault-tolerance - double faultTolerance = Math.min(mergeObstacleTolerance, existingObstacleArea*0.01); - - // Compare areas - if (unionArea - faultTolerance <= existingObstacleArea + mergeObstacleArea) { - // Remove both old obstacles, add union - removeObstacle(mergeObstacle); - removeObstacle(existingObstacle); - addObstacle(unionObstacle, false); - - obstaclesOrganized = false; - return unionObstacle; - } - } - } - - return null; - } - - /** - * Register new obstacle with given attributes. - * This method will try to merge this obstacle with other already existing obstacles. - * - * @param startX Start X coordinate - * @param startY Start Y coordinate - * @param width Width - * @param height Height - */ - public void addObstacle(double startX, double startY, double width, double height) { - addObstacle(startX, startY, width, height, true); - } - - /** - * Register new obstacle with given attributes. - * This method will, depending on given argument, try to merge - * this obstacle with other already existing obstacles. - * - * @param startX Start X coordinate - * @param startY Start Y coordinate - * @param width Width - * @param height Height - * @param merge Should this obstacle, if possible, be merged with existing obstacles - */ - public void addObstacle(double startX, double startY, double width, double height, boolean merge) { - Rectangle2D newRect = new Rectangle2D.Double(startX, startY, width, height); - addObstacle(newRect, merge); - } - - /** - * Registers a given obstacle. - * This method will try to merge this obstacle with other already existing obstacles. - * - * @param obstacle New obstacle - */ - public void addObstacle(Rectangle2D obstacle) { - addObstacle(obstacle, true); - } - - /** - * Registers a given obstacle. - * This method will, depending on the given argument, try to - * merge this obstacle with other already existing obstacles. - * - * @param obstacle New obstacle - */ - public void addObstacle(Rectangle2D obstacle, boolean merge) { - // TODO Should we keep the rounding? - obstacle.setRect( - Math.round(obstacle.getMinX()*1000.0) / 1000.0, - Math.round(obstacle.getMinY()*1000.0) / 1000.0, - Math.round(obstacle.getWidth()*1000.0) / 1000.0, - Math.round(obstacle.getHeight()*1000.0) / 1000.0 - ); - - allObstacles.add(obstacle); - outerBounds = outerBounds.createUnion(obstacle); - - if (merge) { - // Check if obstacle can be merged with another obstacle - Rectangle2D mergedObstacle = mergeObstacle(obstacle); - - // Keep merging... - while (mergedObstacle != null) - mergedObstacle = mergeObstacle(mergedObstacle); - } - - obstaclesOrganized = false; - } - - /** - * Remove the given obstacle, if it exists. - * - * @param obstacle Obstacle to remove - */ - public void removeObstacle(Rectangle2D obstacle) { - allObstacles.remove(obstacle); - - recreateOuterBounds(); - obstaclesOrganized = false; - } - - /** - * This method recreates the outer bounds of - * this obstacle area by checking all registered - * obstacles. - * This method should never have to be called directly - * by a user. - */ - public void recreateOuterBounds() { - outerBounds = new Rectangle2D.Double(0,0,0,0); - for (int i=0; i < allObstacles.size(); i++) { - outerBounds = outerBounds.createUnion(allObstacles.get(i)); - } - obstaclesOrganized = false; - } - - /** - * Reorganizes all registered obstacles in order to speed up - * searches for obstacles in spatial areas. - * This method is run automatically - */ - public void reorganizeSpatialObstacles() { - // Remove all spatial obstacles - for (int x=0; x < spatialResolution; x++) - for (int y=0; y < spatialResolution; y++) - allObstaclesSpatial[x][y].removeAllElements(); - - double boxWidth = outerBounds.getWidth() / (double) spatialResolution; - double boxHeight = outerBounds.getHeight() / (double) spatialResolution; - double currentBoxMinX = outerBounds.getMinX(); - double currentBoxMinY = outerBounds.getMinY(); - - // For each box, add obstacles that belong there - for (int x=0; x < spatialResolution; x++) - for (int y=0; y < spatialResolution; y++) { - // Check which obstacles should be in this box - Rectangle2D boxToCheck = new Rectangle2D.Double(currentBoxMinX + x*boxWidth, currentBoxMinY + y*boxHeight, boxWidth, boxHeight); - for (int i=0; i < allObstacles.size(); i++) { - if (allObstacles.get(i).intersects(boxToCheck)) { - allObstaclesSpatial[x][y].add(allObstacles.get(i)); - } - } - } - - obstaclesOrganized = true; - - //printObstacleGridToConsole(); - } - - /** - * Prints a description of all obstacles to the console - */ - public void printObstacleGridToConsole() { - logger.info("<<<<<<< printObstacleGridToConsole >>>>>>>"); - logger.info(". Number of obstacles:\t" + getNrObstacles()); - logger.info(". Outer boundary min:\t" + getOuterBounds().getMinX() + ", " + getOuterBounds().getMinY()); - logger.info(". Outer boundary max:\t" + getOuterBounds().getMaxX() + ", " + getOuterBounds().getMaxY()); - - Vector uniqueSpatialObstacles = new Vector(); - for (int x=0; x < spatialResolution; x++) - for (int y=0; y < spatialResolution; y++) - for (int i=0; i < allObstaclesSpatial[x][y].size(); i++) - if (!uniqueSpatialObstacles.contains(allObstaclesSpatial[x][y].get(i))) - uniqueSpatialObstacles.add(allObstaclesSpatial[x][y].get(i)); - logger.info(". Unique spatial obstacles:\t" + uniqueSpatialObstacles.size()); - - int allSpatialObstacles = 0; - for (int x=0; x < spatialResolution; x++) - for (int y=0; y < spatialResolution; y++) - for (int i=0; i < allObstaclesSpatial[x][y].size(); i++) - allSpatialObstacles++; - logger.debug(". All spatial obstacles:\t" + allSpatialObstacles); - - logger.info(". Spatial map counts:"); - for (int y=0; y < spatialResolution; y++) { - for (int x=0; x < spatialResolution; x++) { - System.out.print(allObstaclesSpatial[x][y].size() + " "); - } - System.out.println(""); - } - - } - - /** - * Returns XML elements representing the current obstacles. - * - * @see #setConfigXML(Collection) - * @return XML elements representing the obstacles - */ - public Collection getConfigXML() { - Vector config = new Vector(); - Element element; - - for (Rectangle2D rect: allObstacles) { - element = new Element("obst"); - element.setText(rect.getMinX() + ";" + rect.getMinY() + ";" + rect.getWidth() + ";" + rect.getHeight()); - config.add(element); - } - return config; - } - - /** - * Sets the current obstacles depending on the given XML elements. - * - * @see #getConfigXML() - * @param configXML - * Config XML elements - * @return True if config was set successfully, false otherwise - */ - public boolean setConfigXML(Collection configXML) { - for (Element element : configXML) { - if (element.getName().equals("obst")) { - String rectValues[] = element.getText().split(";"); - Rectangle2D newObst = new Rectangle2D.Double( - Double.parseDouble(rectValues[0]), - Double.parseDouble(rectValues[1]), - Double.parseDouble(rectValues[2]), - Double.parseDouble(rectValues[3])); - this.addObstacle(newObst, false); - } - } - return true; - } - -} - diff --git a/tools/cooja/apps/arm/java/se/sics/arm/RayData.java b/tools/cooja/apps/arm/java/se/sics/arm/RayData.java deleted file mode 100644 index 9bd0a8d6d..000000000 --- a/tools/cooja/apps/arm/java/se/sics/arm/RayData.java +++ /dev/null @@ -1,89 +0,0 @@ -package se.sics.arm; - -import java.awt.geom.Line2D; -import java.awt.geom.Point2D; - -/** - * @author Fredrik Osterlind - */ -class RayData { - - enum RayType { ORIGIN, REFRACTION, REFLECTION, DIFFRACTION, DESTINATION } - RayType type; - - private Point2D sourcePoint = null; - private Line2D line = null; - - private int limitOverall = 0; - private int limitRefracted = 0; - private int limitReflected = 0; - private int limitDiffracted = 0; - - /** - * Creates a new ray data instance. - * A ray can be of the following types: - * - * ORIGIN - starting at source point, line should be null - * REFRACTED - ray was refracted at an obstacle, - * source is intersection point with obstacle, line should be null - * REFLECTED - an interval of rays is reflected at given line, - * the source point should be a "psuedo-source" is located behind it - * (as if one was looking from given source point through given line) - * DIFFRACTED - a ray is diffracted at given source point, - * line should be null - * DESTINATION - * @param type Type of ray (one of the above) - * @param sourcePoint See above - * @param line See above (may be null) - * @param limitOverall Maximum numbers of sub rays this ray may produce - * @param limitRefracted Maximum numbers of refracted sub rays this ray may produce - * @param limitReflected Maximum numbers of reflected sub rays this ray may produce - * @param limitDiffracted Maximum numbers of diffracted sub rays this ray may produce - */ - public RayData( - RayType type, - Point2D sourcePoint, - Line2D line, - int limitOverall, - int limitRefracted, - int limitReflected, - int limitDiffracted - ) { - this.type = type; - this.sourcePoint = sourcePoint; - this.line = line; - this.limitOverall = limitOverall; - this.limitRefracted = limitRefracted; - this.limitReflected = limitReflected; - this.limitDiffracted = limitDiffracted; - } - - public RayType getType() { - return type; - } - - public Point2D getSourcePoint() { - return sourcePoint; - } - - public Line2D getLine() { - return line; - } - - public int getSubRaysLimit() { - return Math.min(limitOverall, limitRefracted + limitReflected + limitDiffracted); - } - - public int getRefractedSubRaysLimit() { - return Math.min(limitOverall, limitRefracted); - } - - public int getReflectedSubRaysLimit() { - return Math.min(limitOverall, limitReflected); - } - - public int getDiffractedSubRaysLimit() { - return Math.min(limitOverall, limitDiffracted); - } - -} diff --git a/tools/cooja/apps/arm/java/se/sics/arm/RayPath.java b/tools/cooja/apps/arm/java/se/sics/arm/RayPath.java deleted file mode 100644 index dffb1ffb7..000000000 --- a/tools/cooja/apps/arm/java/se/sics/arm/RayPath.java +++ /dev/null @@ -1,71 +0,0 @@ -package se.sics.arm; - -import java.awt.geom.Line2D; -import java.awt.geom.Point2D; -import java.util.Vector; - -/** - * @author Fredrik Osterlind - */ -public class RayPath { - private Vector points = new Vector(); - private Vector types = new Vector(); - - public void addPoint(Point2D point, RayData.RayType type) { - points.insertElementAt(point, 0); - types.insertElementAt(type, 0); - } - - public int getSubPathCount() { - return points.size() - 1; - } - - public Line2D getSubPath(int pos) { - return new Line2D.Double(points.get(pos), points.get(pos + 1)); - } - - public Point2D getPoint(int i) { - return points.get(i); - } - - public RayData.RayType getType(int i) { - return types.get(i); - } - - public String toString() { - if (points.size() != types.size()) - return "Malformed ray path (differing sizes)"; - - if (points.size() == 0) - return "Empty ray path"; - - if (types.firstElement() != RayData.RayType.ORIGIN && types.lastElement() != RayData.RayType.ORIGIN) - return "Malformed ray path (not closed)"; - - if (types.firstElement() != RayData.RayType.DESTINATION && types.lastElement() != RayData.RayType.DESTINATION) - return "Malformed ray path (not closed)"; - - if (types.firstElement() == types.lastElement()) - return "Malformed ray path (last == first element)"; - - String retVal = ""; - for (int i=0; i < types.size(); i++) { - RayData.RayType currentType = types.get(i); - if (currentType == RayData.RayType.DESTINATION) - retVal = retVal + " DEST "; - else if (currentType == RayData.RayType.DIFFRACTION) - retVal = retVal + " DIFF "; - else if (currentType == RayData.RayType.ORIGIN) - retVal = retVal + " ORIG "; - else if (currentType == RayData.RayType.REFLECTION) - retVal = retVal + " REFL "; - else if (currentType == RayData.RayType.REFRACTION) - retVal = retVal + " REFR "; - else - retVal = retVal + " ???? "; - } - return retVal; - - } - -} diff --git a/tools/cooja/apps/arm/java/statistics/CDF_Normal.java b/tools/cooja/apps/arm/java/statistics/CDF_Normal.java deleted file mode 100644 index ccea768d4..000000000 --- a/tools/cooja/apps/arm/java/statistics/CDF_Normal.java +++ /dev/null @@ -1,216 +0,0 @@ -package statistics; - -//Gaussian CDF Taylor approximation -//Code borrowed from http://www1.fpl.fs.fed.us/distributions.html 19/9 2006 - -/** -* -*This class contains routines to calculate the -*normal cumulative distribution function (CDF) and -*its inverse. -* -*@version .5 --- June 7, 1996 -*@version .6 --- January 10, 2001 (normcdf added) -* -*/ - -public class CDF_Normal extends Object { - -/** -* -*This method calculates the normal cdf inverse function. -*

-*Let PHI(x) be the normal cdf. Suppose that Q calculates -*1.0 - PHI(x), and that QINV calculates QINV(p) for p in (0.0,.5]. -*Then for p .le. .5, x = PHIINV(p) = -QINV(p). -*For p .gt. .5, x = PHIINV(p) = QINV(1.0 - p). -*The formula for approximating QINV is taken from Abramowitz and Stegun, -*Handbook of Mathematical Functions, Dover, 9th printing, -*formula 26.2.3, page 933. The error in x is claimed to -*be less than 4.5e-4 in absolute value. -* -*@param p p must lie between 0 and 1. xnormi returns -* the normal cdf inverse evaluated at p. -* -*@author Steve Verrill -*@version .5 --- June 7, 1996 -* -*/ - -// FIX: Eventually I should build in a check that p lies in (0,1) - - public static double xnormi(double p) { - - double arg,t,t2,t3,xnum,xden,qinvp,x,pc; - - final double c[] = {2.515517, - .802853, - .010328}; - - final double d[] = {1.432788, - .189269, - .001308}; - - if (p <= .5) { - - arg = -2.0*Math.log(p); - t = Math.sqrt(arg); - t2 = t*t; - t3 = t2*t; - - xnum = c[0] + c[1]*t + c[2]*t2; - xden = 1.0 + d[0]*t + d[1]*t2 + d[2]*t3; - qinvp = t - xnum/xden; - x = -qinvp; - - return x; - - } - - else { - - pc = 1.0 - p; - arg = -2.0*Math.log(pc); - t = Math.sqrt(arg); - t2 = t*t; - t3 = t2*t; - - xnum = c[0] + c[1]*t + c[2]*t2; - xden = 1.0 + d[0]*t + d[1]*t2 + d[2]*t3; - x = t - xnum/xden; - - return x; - - } - - } - - -/** -* -*This method calculates the normal cumulative distribution function. -*

-*It is based upon algorithm 5666 for the error function, from:

-*

-*       Hart, J.F. et al, 'Computer Approximations', Wiley 1968
-*
-*

-*The FORTRAN programmer was Alan Miller. The documentation -*in the FORTRAN code claims that the function is "accurate -*to 1.e-15."

-*Steve Verrill -*translated the FORTRAN code (the March 30, 1986 version) -*into Java. This translation was performed on January 10, 2001. -* -*@param z The method returns the value of the normal -* cumulative distribution function at z. -* -*@version .5 --- January 10, 2001 -* -*/ - - -/* - -Here is a copy of the documentation in the FORTRAN code: - - SUBROUTINE NORMP(Z, P, Q, PDF) -C -C Normal distribution probabilities accurate to 1.e-15. -C Z = no. of standard deviations from the mean. -C P, Q = probabilities to the left & right of Z. P + Q = 1. -C PDF = the probability density. -C -C Based upon algorithm 5666 for the error function, from: -C Hart, J.F. et al, 'Computer Approximations', Wiley 1968 -C -C Programmer: Alan Miller -C -C Latest revision - 30 March 1986 -C - -*/ - - public static double normp(double z) { - - double zabs; - double p; - double expntl,pdf; - - final double p0 = 220.2068679123761; - final double p1 = 221.2135961699311; - final double p2 = 112.0792914978709; - final double p3 = 33.91286607838300; - final double p4 = 6.373962203531650; - final double p5 = .7003830644436881; - final double p6 = .3526249659989109E-01; - - final double q0 = 440.4137358247522; - final double q1 = 793.8265125199484; - final double q2 = 637.3336333788311; - final double q3 = 296.5642487796737; - final double q4 = 86.78073220294608; - final double q5 = 16.06417757920695; - final double q6 = 1.755667163182642; - final double q7 = .8838834764831844E-1; - - final double cutoff = 7.071; - final double root2pi = 2.506628274631001; - - zabs = Math.abs(z); - -// |z| > 37 - - if (z > 37.0) { - - p = 1.0; - - return p; - - } - - if (z < -37.0) { - - p = 0.0; - - return p; - - } - -// |z| <= 37. - - expntl = Math.exp(-.5*zabs*zabs); - - pdf = expntl/root2pi; - -// |z| < cutoff = 10/sqrt(2). - - if (zabs < cutoff) { - - p = expntl*((((((p6*zabs + p5)*zabs + p4)*zabs + p3)*zabs + - p2)*zabs + p1)*zabs + p0)/(((((((q7*zabs + q6)*zabs + - q5)*zabs + q4)*zabs + q3)*zabs + q2)*zabs + q1)*zabs + - q0); - - } else { - - p = pdf/(zabs + 1.0/(zabs + 2.0/(zabs + 3.0/(zabs + 4.0/ - (zabs + 0.65))))); - - } - - if (z < 0.0) { - - return p; - - } else { - - p = 1.0 - p; - - return p; - - } - - } - -} \ No newline at end of file diff --git a/tools/cooja/apps/arm/java/statistics/Gaussian.java b/tools/cooja/apps/arm/java/statistics/Gaussian.java deleted file mode 100644 index 4a302fb2b..000000000 --- a/tools/cooja/apps/arm/java/statistics/Gaussian.java +++ /dev/null @@ -1,63 +0,0 @@ -package statistics; - -// Gaussian CDF Taylor approximation -// Code borrowed from http://www.cs.princeton.edu/introcs/21function/Gaussian.java.html 19/9 2006 - -/************************************************************************* -* Compilation: javac Gaussian.java -* Execution: java Gaussian x mu sigma -* -* Function to compute the Gaussian pdf (probability density function) -* and the Gaussian cdf (cumulative density function) -* -* % java Gaussian 820 1019 209 -* 0.17050966869132111 -* -* % java Gaussian 1500 1019 209 -* 0.9893164837383883 -* -* % java Gaussian 1500 1025 231 -* 0.9801220907365489 -* -*************************************************************************/ - -public class Gaussian { - - // return phi(x) = standard Gaussian pdf - public static double phi(double x) { - return Math.exp(-x*x / 2) / Math.sqrt(2 * Math.PI); - } - - // return phi(x) = Gaussian pdf with mean mu and stddev sigma - public static double phi(double x, double mu, double sigma) { - return phi((x - mu) / sigma) / sigma; - } - - // return Phi(z) = standard Gaussian cdf using Taylor approximation - public static double Phi(double z) { - if (z < -8.0) return 0.0; - if (z > 8.0) return 1.0; - double sum = 0.0, term = z; - for (int i = 3; sum + term != sum; i += 2) { - sum = sum + term; - term = term * z * z / i; - } - return 0.5 + sum * phi(z); - } - - - - // return Phi(z, mu, sigma) = Gaussian cdf with mean mu and stddev sigma - public static double Phi(double z, double mu, double sigma) { - return Phi((z - mu) / sigma); - } - - - public static void main(String[] args) { - double z = Double.parseDouble(args[0]); - double mu = Double.parseDouble(args[1]); - double sigma = Double.parseDouble(args[2]); - System.out.println(Phi(z, mu, sigma)); - } - -} diff --git a/tools/cooja/apps/arm/java/statistics/GaussianWrapper.java b/tools/cooja/apps/arm/java/statistics/GaussianWrapper.java deleted file mode 100644 index 5d196fa28..000000000 --- a/tools/cooja/apps/arm/java/statistics/GaussianWrapper.java +++ /dev/null @@ -1,50 +0,0 @@ -package statistics; - -public class GaussianWrapper { - - /** - * Returns standard Gaussian cdf approximation based on algortihm for error function. - * - * @param value Value - * @return Probability - */ - public static double cdfErrorAlgo(double value) { - return CDF_Normal.normp(value); - } - - /** - * Returns Gaussian cdf approximation based on algorithm for error function. - * - * @param value Value - * @param mean Mean value - * @param stdDev Standard deviance - * @return Probability - */ - public static double cdfErrorAlgo(double value, double mean, double stdDev) { - return CDF_Normal.normp((value - mean) / stdDev); - } - - /** - * Returns standard Gaussian cdf using Taylor approximation. - * - * @param value Value - * @return Probability - */ - public static double cdfTaylor(double value) { - return Gaussian.Phi(value); - } - - /** - * Returns Gaussian cdf using Taylor approximation . - * - * @param value Value - * @param mean Mean value - * @param stdDev Standard deviance - * @return Probability - */ - public static double cdfTaylor(double value, double mean, double stdDev) { - return Gaussian.Phi(value, mean, stdDev); - } - -} - diff --git a/tools/cooja/apps/arm/lib/arm.jar b/tools/cooja/apps/arm/lib/arm.jar deleted file mode 100644 index a8d90ad19..000000000 Binary files a/tools/cooja/apps/arm/lib/arm.jar and /dev/null differ diff --git a/tools/cooja/apps/arm/lib/jcommon-1.0.0.jar b/tools/cooja/apps/arm/lib/jcommon-1.0.0.jar deleted file mode 100644 index c5d23f4ae..000000000 Binary files a/tools/cooja/apps/arm/lib/jcommon-1.0.0.jar and /dev/null differ diff --git a/tools/cooja/apps/arm/lib/jfreechart-1.0.1.jar b/tools/cooja/apps/arm/lib/jfreechart-1.0.1.jar deleted file mode 100644 index 6a015249b..000000000 Binary files a/tools/cooja/apps/arm/lib/jfreechart-1.0.1.jar and /dev/null differ