Subject: [Geopriv] geopriv-policy randomization visualization

From: "Thomson, Martin" <[email-masked]>
Date: Thu, 19 Aug 2010 12:21:43 +0800

The following processing script shows the proposed algorithm for location randomization/obscuring.  Credit to Robert for the script that this is based on.

This can be run in Processing (http://processing.org/).

Info:
   The location (shown with a black "+") moves randomly.
   The red circle shows what is sent to a recipient.
   The cyan circle is the trigger circle - when the location moves outside this circle, a new location is created
   The yellow "+" shows where the location was at the time that the location was last updated

Controls:
   Click mouse to pause/unpause
   Drag mouse to move the location directly
   Left and right arrow to adjust the amount of obscuring
   Up and down arrow to adjust the uncertainty of the location

--- fuzz.pde ---

Fuzzer fuzz;
float uncertaintyStep = 2.5; // uncertainty starts at this
float obscureDistance = 50;  // uncertainty is increased to this

void setup() {
  size(600,600);
  smooth();
  background(255);
  ellipseMode(RADIUS);
  textFont(loadFont("CenturyGothic-12.vlw"));
  textMode(SCREEN);
  textAlign(LEFT);
  fuzz = new Fuzzer();
}

void draw() {
  fuzz.update();
}

void mouseReleased() {
  fuzz.togglePause();
}
void mouseDragged() {
  fuzz.drag();
}

void keyPressed() {
  if (key == CODED) {
    if (keyCode == UP) {
      fuzz.incrementUncertainty(uncertaintyStep);
    } 
    else if (keyCode == DOWN) {
      fuzz.incrementUncertainty(-uncertaintyStep);
    }
    else if (keyCode == LEFT) {
      obscureDistance = max(0, obscureDistance - uncertaintyStep);
    } 
    else if (keyCode == RIGHT) {
      obscureDistance = obscureDistance + uncertaintyStep;
    }
  }
}

class Fuzzer {
  int throttle = 0;
  int step;
  boolean paused = false;
  boolean dragging = false;

  PVector location;
  float uncertainty = uncertaintyStep;

  // the centre of the circle that is reportedLocation
  PVector reportedLocation;
  // the location that we use to determine whether to provide a new location
  PVector triggerLocation;
  // the distance from the trigger location at which we generate a new location  
  float threshold;
  // the location at the time that we last provided a new location
  PVector oldLocation;

  // for randomly moving a point around
  Mover mover;

  Fuzzer() {
    location = new PVector(width / 2, height / 2);
    mover = new Mover(); 
    incrementUncertainty(0);
    this.newLocation();
  }

  void togglePause() {
    if (!dragging) {
      paused = !paused;
    }
    dragging = false;
  }

  void incrementUncertainty(float incr) {
    uncertainty = max(uncertaintyStep, uncertainty + incr);
    // fudge factors
    mover.setTopSpeed(2*sqrt(uncertainty));
    step = 2 + round(2*sqrt(uncertainty));
  }

  void drag() {
    PVector m = new PVector(mouseX, mouseY);
    if (PVector.sub(m, this.location).mag() > 0) {
      dragging = true;
      location = m;
      this.update();
    }
  }

  void update() {
    if ((paused && !dragging) || (throttle++ % step) != 0) {
      return;
    }

    if (location.dist(triggerLocation) > threshold) {
      this.newLocation();
    }

    if (!dragging) {
      location = mover.movePoint(location);
    }

    this.display();
  }

  // we need to report a new location because the current real location has moved too far
  void newLocation() {
    oldLocation = location.get();

    // the location that is reported encloses the location of the target
    // this includes the uncertainty, but it is otherwise random
    reportedLocation = location.get();
    reportedLocation.add(this.randomVector(max(0, obscureDistance - uncertainty)));

    triggerLocation = location.get();
    // only move the trigger location by half the obscuring distance
    // this ensures that new locations are generated when the straight line 
    // movement is from 0.5 to 1.5 times the obscuring distance
    triggerLocation.add(this.randomVector(obscureDistance/2));
    // moving the trigger location is sufficient randomization for triggering
    threshold = obscureDistance;
  }

  PVector randomVector(float maxSize) {
    float theta = random(0, TWO_PI);
    PVector r = new PVector(sin(theta), cos(theta));
    r.mult(maxSize*sqrt(random(1)));
    return r;
  }

  void display() {
    noStroke();
    fill(255,10);
    rect(0,0,width,height);
    fill(255);
    rect(0,0,110,36);
    fill(0);
    text("Obscure: " + obscureDistance, 0, 13);
    text("Uncertainty: " + uncertainty, 0, 27);

    stroke(0);
    fill(220,0,0,20);
    float repRadius = max(obscureDistance, uncertainty);
    ellipse(reportedLocation.x, reportedLocation.y, repRadius, repRadius);
    fill(0,220,110,20);
    ellipse(triggerLocation.x, triggerLocation. y,threshold, threshold);
    stroke(0);
    showLocation(location, uncertainty);
    stroke(220, 220, 0);
    showLocation(oldLocation, uncertainty);
  }
  void showLocation(PVector pt, float unc) {
    //    ellipse(pt.x,pt.y,unc,unc);
    line(pt.x - unc, pt.y, pt.x + unc, pt.y);
    line(pt.x, pt.y - unc, pt.x, pt.y + unc);
  }
}

class Mover {
  PVector velocity;
  float topspeed = 4;
  float maxChange = 0.5; // maximum change in velocity for less erratic movement

  Mover() {
    velocity = new PVector(0,0);
  }

  void setTopSpeed(float top) {
    topspeed = top;
  }

  PVector movePoint(PVector location) {
    float rx = random(-topspeed*maxChange, topspeed*maxChange);
    float ry = random(-topspeed*maxChange, topspeed*maxChange);
    PVector delta = new PVector(rx, ry);
    velocity.add(delta);
    velocity.limit(topspeed);
    location.add(velocity);
    location.x = (location.x + width) % width;
    location.y = (location.y + height) % height;
    return location;
  }
}