/* * Copyright (c) 2005-2011 KOM - Multimedia Communications Lab * * This file is part of PeerfactSim.KOM. * * PeerfactSim.KOM is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * PeerfactSim.KOM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PeerfactSim.KOM. If not, see . * */ package de.tud.kom.p2psim.impl.network.modular.st.positioning; import java.util.Random; import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB; import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy; import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; /** * Applies a uniformly-distributed random position on a 2-or multi-dimensional * torus surface. Parameters: torusDimensionSize(double), noOfDimensions(int) * * @author Leo Nobach * */ public class TorusPositioning implements PositioningStrategy { private int noOfDimensions = 2; double torusDimensionSize = 1d; double halfTorusDimensionSize = 0.5d; Random rand = Randoms.getRandom(TorusPosition.class); @Override public Location getPosition(SimHost host, NetMeasurementDB db, NetMeasurementDB.Host hostMeta) { double[] rawPos = getRawTorusPositionFor(host); assert rawPos.length == noOfDimensions : "The raw torus position returned by getRawTorusPositionFor(Host) does not return an array of length " + noOfDimensions + ", instead it returns one with the length " + rawPos.length; return new TorusPosition(rawPos); } /** * May be overridden for more detailled torus positioning. * * @param host * @return */ protected double[] getRawTorusPositionFor(SimHost host) { double[] result = new double[noOfDimensions]; for (int i = 0; i < noOfDimensions; i++) result[i] = rand.nextDouble() * halfTorusDimensionSize * 2; return result; } /** * To be set by the configurator. * * @param noOfDimensions */ public void setNoOfDimensions(int noOfDimensions) { this.noOfDimensions = 2; } /** * To be set by the configurator. * * @param torusDimensionSize */ public void setTorusDimensionSize(double torusDimensionSize) { this.torusDimensionSize = torusDimensionSize; this.halfTorusDimensionSize = torusDimensionSize * 0.5d; } public class TorusPosition extends PositionVector { TorusPosition(double[] rawPos) { super(rawPos); } @Override public double distanceTo(Location netPosition) { if (!(netPosition instanceof PositionVector)) throw new AssertionError( "Can not calculate distances between different position classes: " + this.getClass() + " and " + netPosition.getClass()); TorusPosition other = (TorusPosition) netPosition; double accuDistanceSq = 0; for (int i = 0; i < getDimensions(); i++) { double distDim = getEntry(i) - other.getEntry(i); if (distDim > halfTorusDimensionSize) { // we wrap the torus distDim = torusDimensionSize - distDim; } else if (distDim < -halfTorusDimensionSize) { // we wrap the torus, other way distDim = -torusDimensionSize + distDim; } accuDistanceSq += distDim * distDim; } return Math.sqrt(accuDistanceSq); } @Override public int getTransmissionSize() { return 8 * getDimensions(); // 2 * double } public double[] getRawPos() { return asDoubleArray(); } @Override public TorusPosition clone() { return new TorusPosition(asDoubleArray()); } } @Override public void writeBackToXML(BackWriter bw) { bw.writeSimpleType("torusDimensionSize", torusDimensionSize); bw.writeSimpleType("torusDimensionSize", torusDimensionSize); } }