Series of latitude and longitude points to a 2D polygon

Hello!

I’m trying to convert a series of latitude and longitude points to show up as a polygon at scale in p5.js

for example starting with the following series of lat/lon points

44.964782, -93.276922
44.964125, -93.266912
44.918733, -93.241098
44.924925, -93.331771

I’d like to somehow get an output of a rendering of a polygon that takes up the whole canvas.

so something like:

47%20PM

function setup() {
  createCanvas(400, 400);
}

function draw() {
  console.log(mouseX,mouseY)
  background(220);
  
  
  beginShape()
  vertex(91,69)
  vertex(283,81)
  vertex(285,307)
  vertex(107,238)
  vertex(81,190)
  
  endShape(CLOSE)
  
}

Here is something that I tried, but it’s wayyyyy tooo small.

function setup() {
  createCanvas(400, 400);
    background(220);

  
    beginShape()
  
      let first = ll2c( 44.964782, -93.276922)
      console.log(first)
      vertex(first.x,first.y)
      let second = ll2c(44.964125, -93.266912)
      console.log(second)

      vertex(second.x,second.y)
      let third = ll2c(44.918733, -93.241098)
      vertex(third.x,third.y)
      let forth = ll2c(44.924925, -93.331771)
      vertex(forth.x,forth.y)
  
    endShape()
}

function draw() { }


function ll2c(lat, lon){
  
  let latOut = map(lat, -90, 90, 0, 400);
  let lonOut = map(lon, -180,180,0,400);
  
  return createVector(latOut, lonOut);
  
  
}
1 Like

I would change the map function to be controlled by some min and max variables.

// Global variables
let latMin = 90;
let latMax = -90;
let lonMin = 180;
let lonMax = -180;
// might seem counterintuitive but start the max and min with opposite values.

// Change the drawing code to draw because this won't work with one pass. It needs at least 2.

function 112c(lat, lon) {
  if (lat < latMin) {
    latMin = lat;
  } else if (lat > latMax) {
    latMax = lat;
  }
  // same code block for lonMin and lonMax
  let latOut = map(lat, latMin, latMax, 0, width);
  let lonOut = map(lon, lonMin, lonMax, 0, height);
  return createVector(latOut, lonOut);
}

This isn’t the most elegant code but I hope it gets the idea across. If you calculate the max and min of each value you can map between them. You could split the min and max out in to a separate function.

1 Like

One approach is to map your point coordinates onto your drawing surface.

Another approach is to make your drawing coordinate system match your data, e.g. with translate and scale.

https://p5js.org/reference/#/p5/scale

Note however that Processing features like stroke width, and caps etc. aren’t always robust when you scale down into decimal sizes – so you might want still want to multiply your lat/long by a factor of 100 or 1000 before translating and scaling to meet the data.

Hi @kkisin!

Here’s a full example, the key is to feed in the min/max from the points that are in the polygon to ‘scale’ the whole thing up to the ‘map-scale’ that the polygon is working on. Although, of course this does not take into account the 3d→2d distortion.


// Global variables
let latMin = 44.964782;
let latMax = 44.918733;
let lonMin = -93.241098;
let lonMax = -93.331771;
// might seem counterintuitive but start the max and min with opposite values. (these get set from the min/max points that you feed into the polygon generator)

function setup() {
  createCanvas(400, 400);
    background(220);

  

}

function draw() {
    background(220);

    beginShape()
  
      let first = ll2c( 44.964782, -93.276922)
      // console.log(first)
      vertex(first.x,first.y)
  
      let second = ll2c(44.964125, -93.266912)
      // console.log(second)
      vertex(second.x,second.y)
  
      let third = ll2c(44.918733, -93.241098)
      vertex(third.x,third.y)
  
      let forth = ll2c(44.924925, -93.331771)
      vertex(forth.x,forth.y)
  
    endShape(CLOSE)

}

function ll2c(lat, lon) {
  
  if (lat < latMin) {
    latMin = lat;
  } else if (lat > latMax) {
    latMax = lat;
  }
  
  if (lon < lonMin) {
    lonMin = lon;
  } else if (lon > lonMax) {
    lonMax = lon;
  }
  
  let latOut = map(lat, latMin, latMax, 0, width);
  let lonOut = map(lon, lonMin, lonMax, 0, height);
  return createVector(latOut, lonOut);
}

1 Like

Here’s an idea where everything is inside of a function and it takes an array of lat/lon points to make the shape and uses a rotation to re-orient the shape to “north” aka. ↑ :

https://editor.p5js.org/benmoren/sketches/wpRC6pzpd

//an array of objects containing lat / lon points
//eg:   {"lat" : 44.964782 , "lon" : -93.276922 }
let latlonArray = [
    {"lat" : 44.964782, "lon" : -93.276922 },
    {"lat" : 44.964125, "lon" : -93.266912 },
    {"lat" : 44.918733, "lon" : -93.241098 },
    {"lat" : 44.924925, "lon" : -93.331771 },
]


function setup() {
  createCanvas(400, 400);
  background(220);
}

function draw() {
  background(220);

  ll2poly(latlonArray); //the magic!
  
}

function ll2poly(latlonArray) {
  
  // local variables
  let latMin = 0; // bigger
  let latMax = 0; // smaller
  let lonMin = 0; // bigger (remember negatives)
  let lonMax = 0; // smaller (remember negatives)
  // might seem counterintuitive but start the max and min with opposite values. 
    
  //just set these to the first slot so we have something to comapre to in order to calculate the min/max
  latMin = latlonArray[0].lat
  latMax = latlonArray[0].lat
  lonMin = latlonArray[0].lon
  lonMax = latlonArray[0].lon
  
  // console.log(latMin, latMax, lonMin, lonMax);

  // loop through each lat/lon and check to see it it's actually the min/max
  for(let i = 0 ; i < latlonArray.length; i ++ ) { 
    
    if(latlonArray[i].lat >= latMin){
      latMin = latlonArray[i].lat
    }
    
    if(latlonArray[i].lat <= latMax){
      latMax = latlonArray[i].lat
    }
    
    if(latlonArray[i].lon >= lonMin){
      lonMin = latlonArray[i].lon
    }
    
    if(latlonArray[i].lon <= lonMax){
      lonMax = latlonArray[i].lon
    }
    
    
  }
  
  //push and pop so that the styles dont change anything else in the sketch and so we can cleanly translate and rotate
  push()
  //we can translate and rotate here to correct the orientation of the shape to face "north"/up
  translate(height,0);
  rotate(radians(90)) //rotate by 90 degrees
  beginShape()
  //loop through each point, scale to the min/max and adda vertex for drwaing.
    for(let j = 0 ; j < latlonArray.length; j ++){
      let latOut = map(latlonArray[j].lat, latMin, latMax, 0, width);
      let lonOut = map(latlonArray[j].lon, lonMin, lonMax, 0, height);
      // return createVector(latOut, lonOut);
      vertex(latOut, lonOut)
    }
  endShape(CLOSE)
  pop()

}
1 Like