Skip to content

Instantly share code, notes, and snippets.

@companje
Created February 10, 2025 21:02
Show Gist options
  • Save companje/9a87b68c5d05341c75842fa6a7c882d3 to your computer and use it in GitHub Desktop.
Save companje/9a87b68c5d05341c75842fa6a7c882d3 to your computer and use it in GitHub Desktop.
Globe Weather API
import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
Vector3D focusPoint = latLonToVector3D(0, 0);
Vector3D nl = latLonToVector3D(52.37, 4.91);
Vector3D ny = latLonToVector3D(40.79, -73.96);
Vector3D jp = latLonToVector3D(36.14, 137.86);
Vector3D north = latLonToVector3D(90, 0);
Vector3D south = latLonToVector3D(-90, 0);
Vector3D india = latLonToVector3D(8.2, 77.45);
Vector3D points[] = {nl, ny, india, jp};
Vector3D targetPoint = nl;
Rotation qTo = getRotationToPoint(targetPoint);
Rotation qNow = new Rotation(focusPoint, 0);
double zRotation;
int currentPointIndex = 0;
PShape sphere;
PImage icon;
void setup() {
size(800, 800, P3D);
noStroke();
sphere = createShape(SPHERE, height/2);
sphere.rotateY(HALF_PI);
sphere.setTexture(loadImage("oneday_20073561211.jpg"));
sphere.setStroke(false);
}
void draw() {
background(0);
lights();
ortho();
translate(width/2, height/2);
qNow = interpolateRotations(qNow, qTo, .1);
applyRotation(qNow);
shape(sphere);
for (Vector3D p : points) {
pushMatrix();
translate((float)p.getX() * height/2, (float)p.getY() * height/2, (float)p.getZ() * height/2);
fill(p==targetPoint ? 255 : 0, p==targetPoint ? 0 : 255, 0);
sphere(10);
fill(255);
if (icon!=null && p==targetPoint) {
translate(-icon.width/2, -icon.height/2);
image(icon, 0,0);
}
popMatrix();
}
}
void applyRotation(Rotation rotation) {
double[][] m = rotation.getMatrix();
applyMatrix(
(float) m[0][0], (float) m[1][0], (float) m[2][0], 0,
(float) m[0][1], (float) m[1][1], (float) m[2][1], 0,
(float) m[0][2], (float) m[1][2], (float) m[2][2], 0,
0, 0, 0, 1);
}
void keyPressed() {
if (key == ' ') {
currentPointIndex = (currentPointIndex + 1) % points.length;
targetPoint = points[currentPointIndex];
qTo = getRotationToPoint(targetPoint);
float lat = (float)vector3DToLatLon(targetPoint).getX();
float lon = (float)vector3DToLatLon(targetPoint).getY();
JSONObject data = loadJSONObject("https://api.openweathermap.org/data/2.5/weather?lat="+lat+"&lon="+lon+"&appid=YOUR_APIKEY&units=metric");
//println(data);
println("name: ", data.getString("name"), data.getJSONObject("sys").getString("country")) ;
JSONObject mainObject = data.getJSONObject("main");
println("temperatuur: "+mainObject.getFloat("temp_min") + "°C");
println("gevoelstemperatuur: "+mainObject.getFloat("feels_like") + "°C");
println("minimum temperatuur: "+mainObject.getFloat("temp_min") + "°C");
println("maximum temperatuur: "+mainObject.getFloat("temp_max") + "°C");
println("vochtigheid: "+mainObject.getFloat("humidity"));
//println(mainObject);
JSONObject weatherObject = data.getJSONArray("weather").getJSONObject(0);
String iconFilename = "weather-icons/" + weatherObject.getString("icon") + "[email protected]";
https://openweathermap.org/img/wn/[email protected]
icon = loadImage(iconFilename);
println(weatherObject.getString("description"));
println(weatherObject.getString("main"));
} else {
float step = 50;
if (key=='[') qTo = qTo.compose(new Rotation(focusPoint, step), RotationConvention.VECTOR_OPERATOR);
if (key==']') qTo = qTo.compose(new Rotation(focusPoint, -step), RotationConvention.VECTOR_OPERATOR);
}
if (key=='x') {
qTo = qTo.compose(new Rotation(focusPoint, -zRotation), RotationConvention.VECTOR_OPERATOR);
}
}
double getZRotationAngle(Rotation rotation) {
double[][] m = rotation.getMatrix(); // Haal de rotatiematrix op
return Math.atan2(m[1][0], m[0][0]); // Bereken de yaw (rotatie rond de Z-as) atan2(sinYaw, cosYaw)
}
Rotation getRotationToPoint(Vector3D point) {
Vector3D initialAxis = Vector3D.crossProduct(focusPoint, point);
if (initialAxis.getNorm() == 0) {
initialAxis = new Vector3D(1, 0, 0); // Kies een willekeurige as als zero en point gelijk zijn
}
initialAxis = initialAxis.normalize();
double initialAngle = Math.acos(Vector3D.dotProduct(focusPoint, point));
Rotation rotationToPoint = new Rotation(initialAxis, initialAngle); // Eerste rotatie: Brengt targetPoint naar voren
zRotation = getZRotationAngle(rotationToPoint); //, focusPoint);
rotationToPoint = rotationToPoint.compose(new Rotation(focusPoint, -zRotation), RotationConvention.VECTOR_OPERATOR);
return rotationToPoint;
}
void mouseDragged() {
Vector3D from = getMouseOnSphere(pmouseX, width-pmouseY);
Vector3D to = getMouseOnSphere(mouseX, width-mouseY);
drag(from, to);
}
void drag(Vector3D from, Vector3D to) {
Vector3D axis = Vector3D.crossProduct(from, to);
if (axis.getNorm() > 0) {
axis = axis.normalize();
double angle = -Math.acos(Vector3D.dotProduct(from, to));
qTo = qTo.compose(new Rotation(axis, angle), RotationConvention.VECTOR_OPERATOR);
}
}
Vector3D getMouseOnSphere(float x, float y) {
x = map(x, 0, width, -1, 1);
y = map(y, 0, height, 1, -1);
float r = x*x+y*y;
return new Vector3D(x, y, r>1 ? 0 : sqrt(1-r)).normalize();
}
Rotation interpolateRotations(Rotation start, Rotation end, float t) {
return new Rotation(start.getQ0() + t * (end.getQ0() - start.getQ0()),
start.getQ1() + t * (end.getQ1() - start.getQ1()),
start.getQ2() + t * (end.getQ2() - start.getQ2()),
start.getQ3() + t * (end.getQ3() - start.getQ3()),
true);
}
Vector3D latLonToVector3D(float lat, float lon) { //in degrees
float x = cos(radians(lat)) * sin(radians(lon));
float y = -sin(radians(lat));
float z = cos(radians(lat)) * cos(radians(lon));
return new Vector3D(x, y, z);
}
Vector2D vector3DToLatLon(Vector3D v) {
float lat = -degrees(asin((float)v.getY()));
float lon = degrees(atan2((float)v.getX(), (float)v.getZ()));
return new Vector2D(lat, lon);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment