Say I have a convex polygon and the coordinates of its vertices. Say I wish to check if a coordinate point is within that polygon. How do I do this without an absurd amount of rectangles?
My idea is adding the coordinate as a vertex of the polygon and then checking if a concave shape is formed. Since the polygon is convex, this method works most of the time for a point within the polygon’s edges. The only exception is when the point passes a certain distance from the polygon; then, a concave shape is still formed when the point is well beyond the border.
Share your ideas! I want to find the most efficient method possible of doing this.
If the point has the coordinates [px,py] then consider the line [px,py]-[dx,dy] where the point [dx,dy] is extremely long way from the polygon so that it is definitely outside the polygon. Now check for intersection between this line and each edge of the shape. If the number of intersections is odd then [px,py] is inside the polygon, if even it is outside.
if you know the color of the polygon and it has one unique color that is different from the background (and all others polygons), use get(x,y). If the colors are the same, you are inside the polygon.
Extra tip: when your different polygons have all the same color, you can use a trick: Make an PGraphics (iirc) and draw the same polygons there (same size) but with unique colors.
Then use get() with the PGraphics and eval the unique number.
Now for something extra: Say I have an array of objects that, when I run a function on them, create the aforementioned polygons. How do I test if a point intersects with one of them?
(It must be possible to add objects to the HashMap and edit their values as well.)
resorts to PVector variables instead
I have multiple polygons that all need to be the same color. Plus, they change opacity throughout.
AND, I also need to exclude certain polygons.
here is an example with unique colors. Without PGraphics.
The Sketch works like this:
The Sketch fills Polygons in an HashMap (you could also use ArrayList) in setup().
It displays the Polygons from the HashMap in draw().
It checks the color where you pressed the mouse against the color of the Polygons in mousePressed(). When a color matches, the Polygon is identified (println(p.id);).
As I said, when they have the same color use an underlying PGraphics (where they don’t change the opacity). See Sketch below, next post.
When they have an id like in my version, you can exclude a set of IDs.
Warm regards,
Chrisir
The Sketch
import java.util.Map;
// Note the HashMap's "key" is a String and "value" is an Poly1
HashMap<String, Poly1> hm = new HashMap<String, Poly1>();
int globalID=0;
void setup() {
size(888, 777);
// Putting key-value pairs in the HashMap
hm.put("Ava", new Poly1());
hm.put("Cait", new Poly1());
hm.put("Casey", new Poly1());
// Using an enhanced loop to iterate over each entry
for (Map.Entry me : hm.entrySet()) {
print(me.getKey() + " is ");
println(me.getValue());
}
}
void draw() {
// We can also access values by their key
Poly1 val = hm.get("Casey");
// println("Casey is " + val.id);
// Using an enhanced loop to iterate over each entry
for (Map.Entry me : hm.entrySet()) {
// print(me.getKey() + " is ");
// println(me.getValue());
Poly1 p = (Poly1) me.getValue();
p.display();
}//for
}
void mousePressed() {
color c1=get(mouseX, mouseY);
// Using an enhanced loop to iterate over each entry
for (Map.Entry me : hm.entrySet()) {
print(me.getKey() + " is ");
println(me.getValue());
Poly1 p = (Poly1) me.getValue();
if (p.col1==c1) {
println(p.id);
return; // leave
}
}//for
}
// ==========================================================================
class Poly1 {
color col1 = color(random(255), random(255), random(255));
PVector[] list = { new PVector (random(width), random(height)),
new PVector (random(width), random(height)),
new PVector (random(width), random(height))
};
int id=globalID++;
void display() {
//
fill(col1);
beginShape();
for (PVector pv : list) {
vertex(pv.x, pv.y);
}
endShape();
}
//
}
NO unique colors visible but internal pg has unique colors
still works when you click with mouse (see println)
(no HashMap needed, ArrayList would do)
use this at end of draw() to see the pg:
if (keyPressed)
image(pg, 0, 0);
The Sketch
import java.util.Map;
// Note the HashMap's "key" is a String and "value" is an Integer
HashMap<String, PolyClass> hm = new HashMap<String, PolyClass>();
int globalID=0;
PGraphics pg;
void setup() {
size(888, 777);
pg = createGraphics(width, height);
// Putting key-value pairs in the HashMap
hm.put("Ava", new PolyClass());
hm.put("Cait", new PolyClass());
hm.put("Casey", new PolyClass());
// Using an enhanced loop to iterate over each entry
for (Map.Entry me : hm.entrySet()) {
print(me.getKey() + " is ");
println(me.getValue());
}
pg.beginDraw();
// Using an enhanced loop to iterate over each entry
for (Map.Entry me : hm.entrySet()) {
// print(me.getKey() + " is ");
// println(me.getValue());
PolyClass p = (PolyClass) me.getValue();
p.displayOnPG();
}//for
pg.endDraw();
}
void draw() {
// We can also access values by their key
// PolyClass val = hm.get("Casey");
// println("Casey is " + val.id);
// Using an enhanced loop to iterate over each entry
for (Map.Entry me : hm.entrySet()) {
// print(me.getKey() + " is ");
// println(me.getValue());
PolyClass p = (PolyClass) me.getValue();
p.display();
}//for
}
void mousePressed() {
color c1=pg.get(mouseX, mouseY);
// Using an enhanced loop to iterate over each entry
for (Map.Entry me : hm.entrySet()) {
PolyClass p = (PolyClass) me.getValue();
if (p.col1==c1) {
println(p.id);
return;
}//if
}//for
}
// ==========================================================================
class PolyClass {
color col1 = color(random(255), random(255), random(255));
PVector[] list = { new PVector (random(width), random(height)),
new PVector (random(width), random(height)),
new PVector (random(width), random(height))
};
int id=globalID++;
void display() {
//
fill(0);
beginShape();
for (PVector pv : list) {
vertex(pv.x, pv.y);
}
endShape();
}
//
void displayOnPG() {
pg.fill(col1);
pg.beginShape();
for (PVector pv : list) {
pg.vertex(pv.x, pv.y);
}
pg.endShape();
}
//
}
When i was working on a similar problem, i calculated the midpoint for each shape, then going through each of the vertices i find the maximum distance from the mid point. This way i can use a radius check using the mouse and the midpoint. If the test passes then i can test the point shape collision. If not move on and test another shapes radius. The midPoint only needs to be calculated once, providing your vertices arent changing, and if the shape is translated then you would update the midpoint based on dx and dy.
Yes if all the vertices are moving in the same direction with the same velocity then the max distance from the midpoint stays the same, however if only some vertices change then you just need to test those to see if they now exceed your maximum or to check if the maximum has decreased.
here is an example where you can click the mouse to add points and create shapes. Please note it works best on pc as I havent coded it to handle touchscreens.