xxxxxxxxxx
290
// This P5 code simulates a GPR profile process on a cylindrical object (i.e. pipe). The code performs a convolution between the waveform generated by a GPR antenna and the reflectivity series representing the subsurface.
// The convolution produced a hyperbola. The hyperbola can be rescaled as a function of distance between the antenna and the object such that the larger the scaling factor, the steeper the slopes (asymptotes) of the hyperbola will be.
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// define the variables
var radius = 25, // radius of the pipe/ cave/ anomaly
left, // Left pixel that pipe movement is limited to
right, // right pixel that pipe movement is limited to
maxHeight, // highest pixel that pipe movement is limited to
minHeight, // lowest pixel that pipe movement is limited to
ps = 300, // initial pixel of the center of the pipe from the top (in y direction)
width, // width of the canvas in pixels
trace = 1, // inital trace #
over = false, // for mouse over the pipe
move = false, // for pipe moving
antennaSize = 25, // The size of the square shaped antenna in pixels
antennaCenter = 45, // The initial location of the center antenna in pixels in x direction
TxCenter,
RxCenter,
TRstep = 10, // number of pixels between each GPR measurment
airSize = 75, // part of canvas for airSize
waveBoxSize, // part of canvas for waveBoxSize; white-box including signal
w = [], // the wavelet
lengthW = 65, // length of wavelet in pixels
amplitudeW = 10, // max amplitude of the wavelet
refl = [], // the reflectivity series
lengthRefl, // length of the reflectivity series
data = [], // convoled GPR data that will be shown as the signal
zerosW = [], // temporary to be used in convolution
zerosRefl = [], // temporary to be used in convolution
collect = 1, // 0 or 1; collect or standalone
vfactor; // series of factors adding to pipe_index equation
// setup () initiates the plotting skeme and canvas and defines the geometry of the plotting
function setup() {
createCanvas(900, 500); // width and height
waveBoxSize = width / 2 +25;
width = width - waveBoxSize; //(width- waveBoxSize) to just have the width of soil box
rectMode(CORNERS);
// left and right side of circle
left = width / 2 - radius;
right = width / 2 + radius;
lengthRefl = height-15 ; // leave room in plot window for x-label (-15)
maxHeight = height - 150;
minHeight = airSize + 0.5 * lengthW;
var colbutton = color(255, 204, 0),
button = createButton("Collect Data");
button.style("background-color", colbutton);
button.position(5, height - 30);
button.mousePressed(Collect_Data);
var resetbutton = color(255, 204, 0),
buttonreset = createButton("RESET");
buttonreset.style("background-color", colbutton);
buttonreset.position(90 , height - 30);
buttonreset.mousePressed(resetSketch);
radio = createRadio();
radio.option('slow velocity',350);
radio.option('med velocity', 100);
radio.option('fast velocity', 1);
radio.style('width','115px');
radio.position(10, 400);
fillBackGround();
drawPipe (); // plot pipe
plotTR (); // plot Transmitter and receiver
}
// fillBackGround() set and reset the background
function fillBackGround() {
stroke(0);
background(222, 184, 135);
//rect for air
fill(color(175, 238, 238));
rect(0, 0, width, airSize);
//rect for waveBox
fill(color(300, 300, 300));
rect(width, 0, width + waveBoxSize, height);
fill(0, 0, 0);
//legend
noStroke();
text("AIR", 10, 30);
text("GROUND", 10, airSize + 100);
text("GPR SIGNAL", width+2, 20);
push()
translate(490, 300)
rotate(-PI/2)
text("two-way travel time (ns)",0,0)
pop()
text("distance (m)", 625, 495);
// text('velocity m/ns', 325, height - 15);
}
// draw () does actual plotting
function draw () {
updatePipe (); // check to see if user wants to move pipe
if (collect > 0) { // check if the collect button is pressed
v = velfactor(antennaCenter);
// print('v is ' + v);
conv (v); // calculate and plot GPR signal
moveTR (); // move Transmitter and receiver to the next location
stroke(0);
fill('black');
}
}
// Collect_Data () check if user has pressed collect data button
function Collect_Data () {
collect = 1;
}
// moveTR () moves Transmitter and receiver
function moveTR () {
clearTR (); //clear the previous Transmitter and receiver
if (antennaCenter < (width - 2 * antennaSize)) {
trace = trace + 1;
antennaCenter = antennaCenter + TRstep; //update position of Transmitter and receiver
}
plotTR (); //plot the new position of Transmitter and receiver
}
// resetSketch () checks if user has pressed 'reset' button, if yes, reset the sketch
function resetSketch (){
antennaCenter = 45;
collect = 0;
trace = 1;
fillBackGround(); // reset the background
drawPipe (); // plot pipe
plotTR (); // plot Transmitter and receiver
}
// plotTR () plots the actual Transmitter and receiver
function plotTR () {
noStroke();
fill(color(0, 0, 0));
rect((antennaCenter - 12 - antennaSize), (airSize - 2), (antennaCenter - 12), (airSize - 2 - antennaSize));
rect((antennaCenter + 12), (airSize - 2), (antennaCenter + 12 + antennaSize), (airSize - 2 - antennaSize));
fill(color(300, 300, 300));
text("T", (antennaCenter - antennaSize / 2 - 16), airSize - antennaSize / 2 + 2);
text("R", (antennaCenter + antennaSize / 2 + 8), airSize - antennaSize / 2 + 2);
//stroke(0);
let v0 = createVector(antennaCenter - 12 - antennaSize/2, airSize+5);
let v1 = createVector(antennaCenter + 12 + antennaSize/2, airSize+10);
let v2 = createVector(width / 2, ps-radius);
drawArrow(v0, v2, 'black', 1);
drawArrow(v2, v1, 'black', 1);
}
// clearTR () clear the previous Transmitter and receiver
function clearTR () {
noStroke();
fill(color(175, 238, 238));
rect((antennaCenter - 12 - antennaSize), (airSize - 2), (antennaCenter - 12), (airSize - 2 - antennaSize));
rect((antennaCenter + 12), (airSize - 2), (antennaCenter + 12 + antennaSize), (airSize - 2 - antennaSize));
text("T", (antennaCenter - antennaSize / 2 - 12), airSize - antennaSize / 2 + 2);
text("R", (antennaCenter + antennaSize / 2 + 8), airSize - antennaSize / 2 + 2);
rect(antennaCenter,airSize-2,24,airSize-2-antennaSize);
//stroke(0);
let v0 = createVector(antennaCenter - 12 - antennaSize/2, airSize+5);
let v1 = createVector(antennaCenter + 12 + antennaSize/2, airSize+10);
let v2 = createVector(width / 2, ps-radius);
drawArrow(v0, v2, color(222,184,135),2);
drawArrow(v2, v1, color(222,184,135),2);
}
// drawPipe () plots the pipe
function drawPipe () {
// Draw pipe
stroke(0);
fill(color(300, 300, 300));
ellipse(width / 2, ps, 2 * radius, 2 * radius);
fill(0, 0, 0);
noStroke();
text("BURIED \nOBJECT", width / 2 + radius + 5, ps);
}
// updatePipe () moves the pipe
function updatePipe () { // move the pipe
// Update the pipe position
// Test if mouse if over the pipe
if (mouseX > left && mouseX < right && mouseY > ps -radius && mouseY < ps + radius) {
over = true;
} else {
over = false;
}
// Set and constrain the position of pipe
if (move) {
ps = mouseY;
ps = constrain(ps, minHeight, maxHeight);
resetSketch ();
fillBackGround ();
drawPipe ()
plotTR ();
}
}
// conv() performs convolution of the waveform and reflectivity series and plots it
function conv (v) {
defineW ();
defineRefl (v);
append(w,zerosRefl);
append(refl,zerosW);
stroke(0);
fill(color(0, 0, 0));
for (var k = 0; k < (w.length +lengthRefl -1) ; k+=5) {
data[k] = 0;
for (var j = 0; j < (lengthRefl+1) ; j+=5) {
if(k-j+1>0) {
data[k] = data[k] + w[j]*refl[k-j];
ellipse(width+72+data[k]+TRstep*trace,k, 1, 1);
}
}
}
}
// defineW () defines the wavelet
function defineW () {
//define the waveform
for (var ii = 0; ii < lengthW; ii+=1) {
w[ii] = 0;
w[ii] = sin(ii/10)*amplitudeW;
zerosW[ii] = 0;
}
}
// defineRefl () defines the reflectivity series
function defineRefl (vfactor) {
//define reflectivity series
for (var iii = 0; iii < lengthRefl; iii+=5) {
refl[iii] = 0;
zerosRefl[iii] = 0;
}
refl[airSize] = 1;
var pipe_index;
pipe_index = (floor(sqrt(sq((ps+vfactor)-radius-airSize)+sq((width/2)-(antennaCenter)))/5)*5);
// ellipse(width+72+TRstep*trace,pipe_index, 5, 5)
// print('dist is ' + pipe_index)
refl[pipe_index+airSize] = 0.8;
}
// velfactor() defines the velocity factor needed to scale the conv results
function velfactor(pos) {
var v;
var a = radio.value();
v = -sin(((pos-45) * PI) / 350)+1;
vfactor = v*a;
return vfactor;
}
// mousePressed() checks if the mouse is clicked or not
function mousePressed() {
if (over) {
move = true;
}
}
// mouseReleased() checks if the mouse is Released or not
function mouseReleased() {
move = false;
}
// draw an arrow from a vector at a given base position
function drawArrow(base, vec, myColor, width) {
push();
stroke(myColor);
strokeWeight(width);
fill(myColor);
// Tx -> Rx
line(antennaCenter-8,airSize-15, antennaCenter+8,airSize-15);
// arrow Tx -> Rx
triangle(antennaCenter+8,airSize-12,antennaCenter+10, airSize-15, antennaCenter+8, airSize-18);
// antenna -> target -> antenna
line(base.x, base.y, vec.x, vec.y);
dir = createVector(vec.x-base.x, vec.y-base.y)
let arrowSize = 7;
translate(vec.x, vec.y);
rotate(dir.heading());
// arrow point to antenna or target
triangle(-arrowSize, arrowSize / 2, -arrowSize, -arrowSize / 2, 0, 0);
pop();
}