# Help with angle/geometry math (oh god, it hurts)

Alright, let me start out by stating the obvious: math is not my strong suit. I know that this is probably simple geometry and your third grade niece probably wrote the proof for it just last week but I just can't figure it out.

I have a 2 dimensional p5.js canvas. I have a runway placed at a random point on the canvas which is a simple rectangular shape I've built using 4 vertexes. This runway can exist in one of 4 orientations: 0 degrees (up/down), 45 degrees (up right/bottom left), 90 degrees (left / right), or 135 degrees (up left/bottom right); and since an airplane can enter the runway from either direction, the inverse entries are easy enough to calculate so 180, 225, 270, and 315 are unnecessary. Each airplane has its own orientation in the form of a p5.Vector, with exactly the same directions (0, 45, 90, 135 degrees) as the runways. Pretty simple.

The goal is to have an airplane be able to fly around the screen (check!), be able to spin around according to key presses (check!), and if the program determines that the plane is in line with a runway, allow the user the option of landing it (waa-waaaah).

Now what I'm having issues with is one of the four runways. 3 are no problem (0 / 90 / 135; for reasons I'll explain below) but the 45 degree one is causing me no end of grief.

For the 0 degree runway (up/down), no problem, we check that the X value of the airplane is somewhere between the minX and maxX of the runway, and we're good. For the 90 degree runway (left/right), we do the same thing but with the Y value.

For the 135 degree runway, it's a little trickier (and this may be completely wrong/lucky, so if it is, please tell me), what I do is since the pixel values of the runway (not transform()ed, since beginShape() doesn't work with transform()) going from top-left to bottom-right will always increase their value at an even rate (at 45 degrees, it's 1 for 1), we can just check if the plane's X minus Y is equal to the runway's X minus Y (plus the width of the runway) and that works too.

The reason that the 45 degree one is giving me so much trouble is that I can't figure out what equation to use to check if the airplane's X and Y values line up with the range of the runway's X and Y values. Since it's going from bottom-left to top-right, the X value gets larger the smaller Y gets which means there isn't a simple way to check.

Finally, I'm sure there is probably a much better, more simplistic way to check every single option with one equation (in fact, knowing that real pilots do this all the time with no issue means there definitely is) but as I said earlier, my geometry skills leave something (a lot?) to be desired and I'm stumped at this point. I'd be happy to just figure this one runway out, but if you know of an easier formula that will work for all options, I'm all ears. At this point, I don't even know what to Google to help myself, so even a strong nudge in the right direction would be appreciated.

Thank you very much for reading this wall of text.

submitted by /u/nexxai

# Minimize a fullScreen window

Could anybody tell me how to minimize the window of a fullScreen sketch? I'm making a simple UI and I'm adding the basic buttons like exit and minimize. I used exit() to close it but can't find the way to minimize it.

submitted by /u/TzombyT

Hello, I'm working on a rfid video player.

when you tap your tag, it should load a video, but so far the previous video does not disappear when loaded, it just loads the current videos on one on top of each other, resulting in pure insanity.

Can someone tell me if there's a way to clear the previous video from canvas.

here's my code:

``import processing.video.*; import processing.serial.*; Serial myPort; // The serial port PrintWriter output; String[] \$videoFiles = { // list of videos "aaaa.mp4", "bbbb.mp4", "cccc.mp4", "dddd.mp4" }; Movie[] \$videos; Movie name; Movie movie; Movie movie_b; Movie movie_c; Movie movie_d; int r, g, b; int myBg = 0; String val; boolean myMovie = false; boolean myMovie_b = false; boolean myMovie_c = false; boolean myMovie_d = false; void setup() { size(960, 600); // Open the port you are using at the rate you want: output= createWriter("data.txt"); myPort = new Serial(this, "/dev/cu.SLAB_USBtoUART", 57600); /* Init videos */ \$videos = new Movie[\$videoFiles.length]; for (int i = 0; i < \$videoFiles.length; i++) { \$videos[i] = new Movie(this, \$videoFiles[i]); \$videos[i].jump(0); // always go to the start of the movie \$videos[i].loop(); // movie when finish will stop \$videos[i].pause(); // action play } frameRate(30); // movie.loop(); } void draw() { background(r, g, b); rfidPort(); if (myMovie == true) { // name = \$videos[0]; movie_A(\$videos[0]); } if (myMovie_b == true) { //name = \$videos[1]; movie_A(\$videos[1]); } if (myMovie_c == true) { // name = \$videos[2]; movie_A(\$videos[2]); } if (myMovie_d == true) { // name = \$videos[3]; movie_A(\$videos[3]); } } /*----------------------------------------------------- -------------------------MOVIE---------------------*/ void movieEvent(Movie m) { m.read(); redraw = true; } void movie_A(Movie name) { image(name, 0, 0, 960, 480); //name.jump(0); // always go to the start of the movie //name.loop(); // movie when finish will stop name.play(); // action play } void rfidPort() { while (myPort.available() > 0) { String inBuffer = myPort.readString(); if (inBuffer != null) { String val = trim(inBuffer); //clean junk for (int i = 0; i < 10; i++) { if (val.equals(rfidTag[i]) == true) { println("GROOOUP A"); myMovie = true; r = 255; g = 0; b = 0; // movie_A(); } } for (int i = 10; i < 20; i++) { if (val.equals(rfidTag[i]) == true) { println("GROOOUP B"); myMovie_b = true; r = 0; g = 255; b = 0; // movie_B(); } } output.println(val); println(val); } } } void dumpRfidTxt() { } ``
submitted by /u/neofuturism

# Question about processing using Leap Motion

Hi everyone! I'm currently trying to develop a processing app using Leap Motion for a uni project. The app that I'm trying to do is an image where it show various animals and if the user uses the leap motion to hover over the animal, it will then play the sound of the animal.

I've managed to get the mouse coordinates so it would be easier to know where the coordinates for each animal are, I also added an ellipse where I want these animals to be at. But it seems that once I use the leap to look for the sound and when I hover over the animal won't work as the coordinates suddenly are somewhere else in the screen.

I even tried to make the image resolution the same size as mine instead of trying to go for a default to present at uni.

Is there a way to add an invisible hit box that will activate with the leap movement, instead of adding the coordinates to the fingerPosition.x/y.

I've tried multiple things, but can't find the solution. Can anyone spot where the issue is?

Thank you

``import ddf.minim.spi.*; import ddf.minim.signals.*; import ddf.minim.*; import ddf.minim.analysis.*; import ddf.minim.ugens.*; import ddf.minim.effects.*; import de.voidplus.leapmotion.*; LeapMotion leap; Minim minim; AudioPlayer[] playlist; AudioPlayer player; PImage img; PImage img2; //A true or false variable to determine whether the menu screen should be active or not boolean menu = true; //Feel free to change the size to anything, it should still work int size = 750; //declaring the color arrays float INTERACTION_SPACE_WIDTH = 200; // left-right from user float INTERACTION_SPACE_DEPTH = 150; // away-and-toward user float FINGER_DOT = 30; void setup () { size(displayWidth, displayHeight, P3D); img = loadImage("farmmenuDMF.png"); img2 = loadImage("farmDMF2.png"); background(0); minim = new Minim(this); noStroke(); fill(50); leap = new LeapMotion(this); //defining the mp3 names and assigning them to reference items playlist = new AudioPlayer [6]; playlist[0] = minim.loadFile("cat.wav"); //cat playlist[1] = minim.loadFile("dog.wav"); //dog playlist[2] = minim.loadFile("chicken.wav"); //chicken playlist[3] = minim.loadFile("pig2.wav"); //pig playlist[4] = minim.loadFile("chicken.wav"); //sheep playlist[5] = minim.loadFile("dog.wav"); //cow } void draw() { background (255); //the call to the leapFunction leapFunction (); image(img2, 0, 0); fill(234,86,250); //pink/cat ellipse(1200, 350, 120,80);//cat fill(255,0,0); //red/dog ellipse(322, 337, 100,100); fill(241,253,72); //yellow/chicken ellipse(1126, 659, 100,100); fill(0,255,0); //green/pig ellipse(473, 447, 150,150); fill(255,0,255); //sheep ellipse(328, 591, 150,150); fill(0,0,255); //blue/cow ellipse(814, 469, 180,180); //The start Screen: if(menu == true) { image(img, 0, 0); fill(150); rect(560,600,100,50); fill(0); text("Play", 593, 630); if ( mousePressed == true && mouseX > 510 && mouseX < 610 && mouseY > 550 && mouseY < 650){ menu = false; } } int fps = leap.getFrameRate(); fill(#00E310); text(fps + " fps", 20, 20); for (Hand hand : leap.getHands ()) { PVector indexTip = hand.getIndexFinger().getRawPositionOfJointTip(); handleFinger(indexTip," "); } ellipse( mouseX, mouseY, 2, 2 ); fill(0); text( "x: " + mouseX + " y: " + mouseY, mouseX, mouseY ); } void handleFinger(PVector pos, String id) { // map finger tip position to 2D surface float x = map(pos.x, -INTERACTION_SPACE_WIDTH, INTERACTION_SPACE_WIDTH, 0, width); float y = map(pos.z, -INTERACTION_SPACE_DEPTH, INTERACTION_SPACE_DEPTH, 0, height); fill(#00E310); noStroke(); ellipse(x, y, FINGER_DOT, FINGER_DOT); } //Leap function that senses finger position and assigns it to the keys void leapFunction () { //int finger_positions = leap.getFrameRate(); // HANDS for(Hand hand : leap.getHands()){ // FINGERS for(Finger finger : hand.getFingers()){ // Basics //finger.draw(); //int finger_id = finger.getId(); PVector finger_position = finger.getPosition(); if(finger_position.x > 1160 && finger_position.x < 1200 && finger_position.z > 300 && finger_position.z < 380 ){ //cat playlist[0].play(); } else playlist[0].pause(); // Touch Emulation int touch_zone = finger.getTouchZone(); //float touch_distance = finger.getTouchDistance(); switch(touch_zone){ case -1: // None break; case 0: // Hovering // println("Hovering (#"+finger_id+"): "+touch_distance); break; case 1: // Touching // println("Touching (#"+finger_id+")"); break; } } } } void stop() { minim.stop(); //super.stop(); } ``
submitted by /u/TRB_S

# Help needed, questions about university mini-project

Hey guys, for my course in Introduction to programming and Problem Resolution, we're studying Processing. We have to do a mini-project where you have to mimic the well-known game Bejeweled, but a simpler version of it.

So far I struggled a bit, this semester was my first contact with the language (Java) and the Processing IDE. There are some guidelines like the Gems have to be implemented as objects and the grid has to be 20x20, but my questions are:

• How can I search within the Gems array for gems that are equal so I can delete them? I tried a method but it seems like it's not going to work because I would need to check all of the 20 rows/columns of the grid... to see if

`` x+1.type==x+2.type==x+3.type==x+4.type==x+5.type... ``
• How do i make the gems "fall"? I realise i need to change the gems to random values to "delete" them, but i don't understand how i make the gems abose occupy the places of the gems that were deleted.

I leave my code so you can help me better, thank you for your attention, and if you have any other tips that you think you can give me then i'm all ears on you. Thanks again.

Main:

``Board board = new Board(); void settings() { size(800, 800, P2D); smooth(2); } void draw() { noFill(); } void setup() { background(255); board.start(); } void mousePressed() { board.selection=board.selection?false:true; board.selectGems(); board.fetchGems(); } ``

Board:

``final int boardWidth = 20; final int boardHeight = 20; Gem[][] gems; class Board { boolean selection=true; int x, y, _x, _y, fX, fY, tX, tY, tType, _tType, h_streak, v_streak; Board() { gems = new Gem[boardWidth][boardHeight]; } void start() { generateBoard(); fetchGems(); } final int gemSize() {//declare gem size 33x33 return 33; } void generateBoard() {//create the 2d array of gems and paint them gem by gem for (int x = 0; x < gems.length; x++) { for (int y = 0; y < gems[0].length; y++) { gems[x][y] = new Gem(); boardGem(x, y, gems[x][y]); } } } void boardGem(int x, int y, Gem gem) { x = x*gemSize(); y = y*gemSize(); if (x+gemSize()<660 && y+gemSize()<660) { fill(gem._colors()); noStroke(); rect(x, y, gemSize(), gemSize()); } else { fill(255); rect(x, y, x+gemSize(), y+gemSize()); } } void selectGems() { x = mouseX/gemSize(); y = mouseY/gemSize(); if (selection==false) { fX = x; fY = y; } else if (selection==true) { tX = x; tY = y; if ((fX<=18 && fY<=18 && tX<=18 && tY<=18) && (gems[fX][fY].getType() != gems[tX][tY].getType()) && (abs(fX-tX)==1 || abs(fY-tY)==1) && !(abs(fX-tX)==1 && abs(fY-tY)==1)) { swapGems(); } else if ((gems[fX][fY].getType() == gems[tX][tY].getType())) { println("Jogada invalida, não podes trocar duas joias iguais."); } else if ((abs(fX-tX)!=1 || abs(fY-tY)!=1)) { println("Jogada invalida, so podes trocar joias que estejam a 1 unidade de distancia."); } } } void swapGems() { int _tType = gems[tX][tY].getType(); int tType = gems[fX][fY].getType(); gems[fX][fY].type=_tType; boardGem(fX, fY, gems[fX][fY]); gems[tX][tY].type=tType; boardGem(tX, tY, gems[tX][tY]); } void fetchGems() { Gem test1 = new Gem(); for (int x=0; x<boardWidth; x++) { for (int y=0; y<boardHeight; y++) { if (x+2<boardWidth) { if (gems[x][y].getType()==gems[x+1][y].getType() && gems[x+1][y].getType()==gems[x+2][y].getType()) { test1=gems[x+2][y]; fetchStreaks(gems[x][y], gems[x+1][y], gems[x+2][y], test1); } } } } } /* void checkBoard() { Gem horizontalHolder = new Gem(); Gem verticalHolder = new Gem(); for(int _x=0;_x<boardWidth;_x++) { for(int _y=0; _y<boardHeight;_y++) { //Horizontal check if(_x+2 < boardWidth && gems[_x][_y].getType() == gems[_x+1][_y].getType() && gems[_x+1][_y].getType() == gems[_x+2][_y].getType()) { if(_x+3 < boardWidth && gems[_x+2][_y].getType() == gems[_x+3][_y].getType()) { horizontalHolder = gems[_x+3][_y]; println("horizontal streak"); fetchStreaks(gems[_x][_y],gems[_x+1][_y],gems[_x+2][_y], gems[_x+3][_y], horizontalHolder, verticalHolder); } } //Vertical check if(_y+2 < boardHeight && gems[_x][_y].getType() == gems[_x][_y+1].getType() && gems[_x][_y+1].getType() == gems[_x][_y+2].getType()) { if(_y+3 < boardHeight && gems[_x][_y+3].getType() == gems[_x][_y+3].getType()) { verticalHolder = gems[_x][_y+3]; println("vertical streak"); fetchStreaks(gems[_x][_y],gems[_x][_y+1],gems[_x][_y+2], gems[_x][_y+3], horizontalHolder, verticalHolder); } } } } } */ void fetchStreaks(Gem gem1, Gem gem2, Gem gem3, Gem gem4) { //state 7 means that the jewels returned from checkBoard will be made equal to a state called pre deletion. gem1.setType(7); gem2.setType(7); gem3.setType(7); gem4.setType(7); for (int x = 0; x<boardWidth; x++) { for (int y = 0; y<boardHeight; y++) { if (gems[x][y].getType() == 7) { //fetch for gems that are ready for deletion for (int i=y; i>=0; i--) { if (i==0) { gems[x][y].setType(gems[x][i].generateType()); } else { gems[x][y].setType(gems[x][i-1].generateType()); } } } } } } } ``

Gem:

``class Gem {//create a single gem, with a type that varies from 1 to 6, being these the different types of gems. private int type; final color colors[] = {color(123, 36, 28), color(91, 44, 111), color(33, 97, 140), color(29, 131, 72), color(212, 172, 13), color(211, 84, 0), color(0, 0, 0)}; color c = colors[getType()]; Gem() {//declares the value returned from generateType() to type. this.type=generateType(); } int generateType() {//returns a value for the type of the gem return int(random(6)); } void setType(int type) {//set the type of the gem this.type=type; } int getType() {//get the type of the gem return type; } color _colors() { return c = colors[getType()]; } } ``
submitted by /u/juan_del_mexico

# Is there an easy way to validate a string as an IP address?

Howdy, I have a simple program that sends formatted rest calls to servers. I provide a field for editing the IP address that the call gets sent to, but I just noticed that if the field contains a non-valid IP (like ".10.203" instead of "192.168.10.203", etc) the thread I'm sending it in will hang for about a minute.

I'm storing the address in a string at the moment, as that's easiest when dealing with user-entered values.

Is there an easy way to validate this without manually inspecting the string for each octet and what not?

submitted by /u/TroyDL

# Albedo Dreams. Experiments in DIY climate manipulation

Mari Keski-Korsu, Albedo Logger (part of Albedo Dreams)

Albedo is the measure of the “whiteness” of a surface and its ability to reflect the sunlight. When applied to the Earth, the albedo effect is a measure of how much of the Sun’s energy can be reflected back into space. Sophisticated, large-scale goeengineering research projects are looking into ways to efficiently do that and thus manipulate climate and put the brake on global warming.

Mari Keski-Korsu, Albedo Dreams Rock Bed, part of Albedo Dreams in Reykjavik, Iceland, 2013. Photo

Since 2012, artist Mari Keski-Korsu has been looking into the DIY strategies that citizens could deploy in order to manipulate climate. She discovered a research paper from engineers at Concordia University who estimated that if cities all over the world increased their surface albedos by adopting white rooftops and light-colored pavements, the global cooling effect generated would be the equivalent of reducing CO2 emissions by 25–150 billion tonnes.

What if citizens joined forces and geoengineered climate on a small scale, both in forests and urban areas? Could they have an impact on the climate without ever needing to resort to costly innovations? Just by using kites, suits for men and semi-domestic forest animals, car covers and other low/no tech guerrilla interventions?

Mari Keski-Korsu, Reindeer in albedo suit (Stuffed reindeer, recycled textile and mosaics.) At Prima Materia exhibition, 2012

Mari Keski-Korsu, Albedo Dreams Kites flying in Reykjavik, Iceland. Photo: Asgerdur G. Gunnarsdottir, 2013

Mari Keski-Korsu, Albedo Logger (part of Albedo Dreams)

Mari Keski-Korsu, Albedo Logger (part of Albedo Dreams)

Keski-Korsu was showing one of her DIY strategies in climate change at the HYBRID MATTERs exhibition which closed a few days ago at Forum Box in Helsinki. This one was a video work showing a suit prototype for forest loggers (i could not embed the video but you can watch it here.) The albedo suit is designed to increase the sunlight reflectivity and thus the albedo value of the forests, cooling the climate in the process while allowing the logger to work as usual. The suit even features a stunning white cape that can be spread out during work breaks and rolled up on the back afterwards.

Of course covering the surface of the Earth in whiteness is all a bit absurd (even though i’m sure Trump would think that a whiter world is the way to go) but that’s why the project echoes with so much sharpness and irony the current research in climate manipulation. Ongoing geoengineering projects often display the typical human hubris that assumes that the best way to save the world is by deploying more technology, more innovation, more energy-devouring ‘solutions.’ And not by taking the problem at its roots: by reflecting on our unruly use and abuse of the planet, by trying to show more respect to all the living entities that populate it.

Albedo Dreams started as a collaboration, organised with the help of Bioart Society and HENVI – Helsinki University Centre for Environment, with forest researchers Frank Berninger and Nea Kuusinen.

Mari Keski-Korsu is collecting all her research and findings in do-it-yourself climate manipulation on her Albedo Dreams website.

Albedo hut village after a children workshop at the Children Cultural Centre Lastu in Lapinlahti, Finland, 2013

Albedo Dreams “whitening actions” in Reykjavik, Iceland in February 2013. Photo

The Albedo Logger video was screened at the HYBRID MATTERs exhibition at Forum Box in Helsinki. The show was part of the HYBRID MATTERs Nordic art&science network program which investigates the convergence of our environment with technology and essentially the intentional and unintentional transformation of our planet through human activity. The program took the form of a series of researches, encounters, art commissions, exhibitions and a symposium. I got the chance to attend the symposium and to visit the final exhibition. More episodes about the whole event coming soon!