Java övning, beräkna total ytarea av flera rektanglar

Permalänk
Medlem

Java övning, beräkna total ytarea av flera rektanglar

Hej alla swecs!

Jag har en sista övning kvar i en kurs, och jag förstår helt enkelt inte vad jag ska göra. Jag vet att det inte är meningen att man ska få kod via Sweclockers, men jag har nu suttit med detta i 4-5 timmar och kommer inte ens fram till hur jag ska börja. Uppgiften går ut på att finna den totala arean som täcks av "fönster" som kan helt, delvis, eller inte överlappa varandra. Input kommer i form av (x,y) punkter för nedre vänstra och övre högra hörn.

Jag har tänkt på dessa metoder: Beräkna totalarean och sedan subtrahera med samtliga täckande areor dvs. se det hela som rektanglar som "staplas", eller beräkna min X + max X och gå därifrån, försöka ta reda på "noderna" där riktningen ändras i 2D-stil.

Jag uppskattar varenda liten knuff jag kan få, jag har suttit och ritat på ett x antal papper och jag är helt slut i huvudet!

Permalänk
Medlem

Javas Area-klass (http://docs.oracle.com/javase/7/docs/api/java/awt/geom/Area.h...) har redan det du behöver.

Börja med en tom Area a
Skapa en ny Area b för varje fönster, och lägg till b till a. (Detta skapar en union av areorna, och därför kommer överlappande bitar av areorna inte räknas)
När du är klar kommer a ha den slutgiltiga arean.

Permalänk
Medlem

Tack så mycket

Permalänk
Medlem
Skrivet av MrMadMan:

Javas Area-klass (http://docs.oracle.com/javase/7/docs/api/java/awt/geom/Area.h...) har redan det du behöver.

Börja med en tom Area a
Skapa en ny Area b för varje fönster, och lägg till b till a. (Detta skapar en union av areorna, och därför kommer överlappande bitar av areorna inte räknas)
När du är klar kommer a ha den slutgiltiga arean.

Jag sitter och går igenom länken, men jag ser inte någon metod som beräknar arean åt en? toString() metoden ger bara minnesplatsen(java.awt.geom.Area@28d93b30). Ska jag försöka använda en pathIterator för att rita upp och beräkna eller hur går man till väga för att få ut arean?

Permalänk
Medlem

Om man kollar som hastigast i dokumentationen så ser jag följande:

// Example: Area a1 = new Area([triangle 0,0 => 8,0 => 0,8]); Area a2 = new Area([triangle 0,0 => 8,0 => 8,8]); a1.add(a2); a1(before) + a2 = a1(after)

Ta en extra titt, försök och se vad som händer?

Visa signatur

Corsair 16GB (4x4096MB) CL9 1600Mhz | Asus P8Z77-V PRO |
Samsung SSD Basic 830-Series 256GB | Intel Core i7 3770K 3,5Ghz |
Asus Xonar Essence STX | Noctua NH-U9B SE2 | Antec Performance One P280 | Corsair HX 850W 80+ Gold Modulär | MSI GTX 770

Permalänk
Medlem
Skrivet av NoPaiN^:

Om man kollar som hastigast i dokumentationen så ser jag följande:

// Example: Area a1 = new Area([triangle 0,0 => 8,0 => 0,8]); Area a2 = new Area([triangle 0,0 => 8,0 => 8,8]); a1.add(a2); a1(before) + a2 = a1(after)

Ta en extra titt, försök och se vad som händer?

Hehe, redan gjort. En förkortad version av min forloop ser ut såhär:

for (int i = 0; i<n; i++){
...
Area b = new Area(new Rectangle(x1,y1,x2,y2));
a.add(b);
}

System.out.println(a); ger då: java.awt.geom.Area@28d93b30
System.out.println(a.getBounds()); ger java.awt.Rectangle[x="0,y=0,width=4,height=4"]

.toString() ger f.övr samma svar som println(a).

Jag försöker hitta någon typ av metod som beräknar totala arean av Area a, alternativt ett sätt där jag själv kan skriva en sådan metod?

En annan undran är: Om jag, efter att ha kört hela forloopen, skapar en Rectangle-objekt av den sammansatta Area a, hur kommer den att se ut då? Den kommer ju inte att faktiskt vara en rektangel eftersom den kommer att ha ett X antal hörn. Ett exempel är t.ex två rektanglar med (x,y) = (0,0)(1,1) & (1,1)(3,3), a.add(b) här kommer ju inte att vara en rektangel?

EDIT: Jag förstår nu att .getBounds() inte är en bra idé, den ger ju tillbaka den minsta rektangel som arean kan vara i. Det förstör ju en hel del. Har gjort om det till en polygon med punkter, där jag läser in samtliga x och y punkter och sen gör en enda polygon av detta. Är fortfarande fast i hur jag ska beräkna arean av denna polygon nu..

Permalänk
Medlem

Jag har aldrig använt mig av geom eller kodar mycket java för övrigt. Men provade att använda contains och det fungerade, dock är den metoden knappast effektivt mot att lösa det på "egen hand". Så om det var sättet tidigare postare syftade på ser jag ingen anledning att blanda in Area-klassen när det bara handlar om hela pixlar.

Permalänk
Medlem

Inser att Area kanske inte alls passade så bra som jag först trodde... Ber om ursäkt om jag har vilselett dig. Men kolla på det här exemplet för hur man räknar ut arean för en polyon: http://www.mathopenref.com/coordpolygonarea2.html

Var extra noga med att läsa delen "Limitations" så att metoden verkligen funkar i det här fallet.

Permalänk
Medlem

Nu vet jag inte om jag har missat något, och sedan så är det ett tag sedan som jag satt med java. men om det är fönster som öppnas så borde de vara av typen window? För i sådana fall kan du väll skippa positionerna helt och bara plocka höjd och bredd?

Ex (något liknande med):
private int GetArea(Window frame)
{
int area = (int)(frame.getWidth() * frame.getHeight()); //Du kanske måste casta om det lite bättre
return area;
}

Sedan är det bara loopa igenom alla fönstren.

Men om du måste köra med x1 och x2 etc, så kan du ta och kolla in lite på Dimension och sedan använda dig utav Window också. Dimension i det här fallet kan fånga upplösningen på skärmen med hjälp av Toolkit.getDefaultToolkit().getScreenSize().
Hur du ska gå till väga får du klura lite på Men det borde ge dig en knuff åt en riktning....även om den kanske är fel (är som sagt inte helt hundra på hur det där var och javan).

Permalänk
Medlem

Enkel (men kanske inte så elegant) lösning: För varje fönster/rektangel generera varje enskild koordinat och lagra i en (gemensam) lista om och endast om en identisk koordinat inte redan finns där. Antalet element i listan är det antal pixlar som fönstren täcker.

Psuedokod nedan:

coordlist = new list for each rectangle { for(xcoord=xmin; xcoord <= xmax; xcoord++) { for(ycoord=ymin; ycoord <= ymax; ycoord++) { xycoord = new pair(xcoord, ycoord) if(!coordlist.contains(xycoord) coordlist.add(xycoord) } } }

Dold text
Visa signatur

Laptop: Dell Latitude E7270 | 12,5" FHD IPS | i5-6300U | 16GB RAM | 500GB SSD
Laptop: MacBook Air 13"
NUC: Intel i5-4250U | 8GB RAM | 250GB SSD

Permalänk
Medlem

Ett "fulhack" kan vara att skapa en boolean array på 10000x10000 och för varje fönster som läggs till sätta alla de värden i arrayen till true. Ett exempel i psudokod är då

Boolean result = new Boolean[100000][10000]; for(int i = 0; i<n; i++){ int x1 = input[i].getx1(); int y1 = input[i].gety1(); int x2 = input[i].getx2(); int y2 = input[i].gety2(); for(int j = x1; j<x2; j++) for(int k = y1; k<y2; k++) result[j][k] = true; } int counter = 0; for(int i = 0; i<10000; i++) for(int j = 0; j<10000; j++) if(result[i][j]) counter++: System.out.println("Upptagen area är " + (float)counter/100000 + " procent"); return counter;

Du får självfallet ändra så att x1,y1... är rätt värden och så att du kollar vilken som är störst av x1 och x2, men konceptet är ganska enkelt

Visa signatur

In the end what separates a man from a slave?
Money? Power? No... A man chooses, a slave obeys.
ASUS Z170M-PLUS || Intel Core i7 6700k @ 4,7GHz || 64GB 2133MHz Corsair RAM || MSI NVIDIA RTX 2070 Gaming Z 8GB || Bifenix Prodigy M || 2x CZ TR150 480GB RAID 0 || BeQuiet DarkRock Pro

Permalänk
Medlem

Jag har återgått till att använda mig av rektanglar. Jag får ett fel som jag inte riktigt förstår, men såhär långt har jag kommit:
tillvägagångssätt:
- beräkna samtliga input till rektanglar
- lägger dem i en array
- beräknar total area
- beräkna total "intersection area" dvs arean som är "på varandra"
- ta total area - intersection area.

Felet uppstår när jag ska beräkna intersection area, det ser jag. Totala arean har jag räknat att det stämmer, den får jag rätt på.

Men den här koden verkar inte fungera som den ska:

for (int i = 0; i<rows; i++){
for(int j=i+1; j<rows; j++){
Rectangle temp = rektangel[i].intersection(rektangel[j]);
int tempInt = (int)(temp.getHeight()*temp.getWidth());
System.out.println(tempInt);
totInt = totInt+tempInt;
}

Förstår inte varför intersections inte blir rätt?

edit: får dessutom vissa NEGATIVA intersections, hur fan går det till?

Permalänk
Medlem
Skrivet av asabla:

Nu vet jag inte om jag har missat något, och sedan så är det ett tag sedan som jag satt med java. men om det är fönster som öppnas så borde de vara av typen window? För i sådana fall kan du väll skippa positionerna helt och bara plocka höjd och bredd?

Ex (något liknande med):
private int GetArea(Window frame)
{
int area = (int)(frame.getWidth() * frame.getHeight()); //Du kanske måste casta om det lite bättre
return area;
}

Sedan är det bara loopa igenom alla fönstren.

Men om du måste köra med x1 och x2 etc, så kan du ta och kolla in lite på Dimension och sedan använda dig utav Window också. Dimension i det här fallet kan fånga upplösningen på skärmen med hjälp av Toolkit.getDefaultToolkit().getScreenSize().
Hur du ska gå till väga får du klura lite på Men det borde ge dig en knuff åt en riktning....även om den kanske är fel (är som sagt inte helt hundra på hur det där var och javan).

Han ska inte faktiskt göra fönster, så varför skulle han använda Windows?. Och sedan ska han beräkna arean som täcks av rektanglarna, inte rektanglarnas sammanlagda area. Läs uppgiften igen!

Permalänk
Medlem
Skrivet av tufflax:

Han ska inte faktiskt göra fönster, så varför skulle han använda Windows?. Och sedan ska han beräkna arean som täcks av rektanglarna, inte rektanglarnas sammanlagda area. Läs uppgiften igen!

Läs gärna mitt inlägg ovanför ditt, jag funderade på att area = sammanlagd area - intersections area, men har fastnat :/

Permalänk
Medlem

dovas92 läste du detta som MrMadMan pasteade? Det är detta du ska använda. http://www.mathopenref.com/coordpolygonarea2.html

Permalänk
Medlem
Skrivet av dovas92:

Jag har återgått till att använda mig av rektanglar. Jag får ett fel som jag inte riktigt förstår, men såhär långt har jag kommit:
tillvägagångssätt:
- beräkna samtliga input till rektanglar
- lägger dem i en array
- beräknar total area
- beräkna total "intersection area" dvs arean som är "på varandra"
- ta total area - intersection area.

Felet uppstår när jag ska beräkna intersection area, det ser jag. Totala arean har jag räknat att det stämmer, den får jag rätt på.

Men den här koden verkar inte fungera som den ska:

for (int i = 0; i<rows; i++){
for(int j=i+1; j<rows; j++){
Rectangle temp = rektangel[i].intersection(rektangel[j]);
int tempInt = (int)(temp.getHeight()*temp.getWidth());
System.out.println(tempInt);
totInt = totInt+tempInt;
}

Förstår inte varför intersections inte blir rätt?

edit: får dessutom vissa NEGATIVA intersections, hur fan går det till?

Iofs, detta borde fungera, så du kanske inte behöver grejen ovan.
EDIT: Förresten så borde det kanske inte alls göra det. Det är krångligare än vad man kan tro. Jag skulle kört på metoden: räkna fram en polygon, sedan arean på den.

Permalänk
Medlem
Skrivet av tufflax:

dovas92 läste du detta som MrMadMan pasteade? Det är detta du ska använda. http://www.mathopenref.com/coordpolygonarea2.html

Ja, jag läste det, försökte det, gav upp.

Skrivet av tufflax:

Iofs, detta borde fungera, så du kanske inte behöver grejen ovan.

Jag känner också att detta borde fungera. Det fungerar tydligen på 2 av 9 testfall. Det är något som jag inte har tänkt på, men vad? :/

Ger en uppdaterad version av min loop också:

for (int i = 0; i<rows; i++){ for(int j=i+1; j<rows; j++){ int tempInt = 0; Rectangle temp = rektangel[i].intersection(rektangel[j]); if(temp.isEmpty() !=true){ tempInt = (int)(temp.getHeight()*temp.getWidth()); // System.out.println(tempInt); } totInt = totInt+tempInt; }

Redigerade in koden i [code]-taggar för att behålla indentering för läsarnas skull.
Permalänk
Hedersmedlem
Skrivet av dovas92:

Ja, jag läste det, försökte det, gav upp.

Jag känner också att detta borde fungera. Det fungerar tydligen på 2 av 9 testfall. Det är något som jag inte har tänkt på, men vad? :/

Ger en uppdaterad version av min loop också:

for (int i = 0; i<rows; i++){ for(int j=i+1; j<rows; j++){ int tempInt = 0; Rectangle temp = rektangel[i].intersection(rektangel[j]); if(temp.isEmpty() !=true){ tempInt = (int)(temp.getHeight()*temp.getWidth()); // System.out.println(tempInt); } totInt = totInt+tempInt; }

Har inte studerat din kod, men kan det vara om det ligger tre eller fler rektanglar på varandra som ställer till det?

Visa signatur

Använd gilla för att markera nyttiga inlägg!

Permalänk
Medlem
Skrivet av giplet:

Har inte studerat din kod, men kan det vara om det ligger tre eller fler rektanglar på varandra som ställer till det?

Njä, koden ska ju jämföra samtliga rektanglar med varandra en gång. Därav de två for-looparna. Uppskattar gärna om du kollar på den snabbt, kanske jag har gjort ett tankefel?

Permalänk
Medlem

Uppdaterade mitt svar ovan.

Jag ritade 3 rektanglar som alla skär varandra. Sen tänkte jag vad som skulle ske med din loop, och det blir fel. Du tar bort för mycket area.

Vad gick fel med polygon-metoden?

Permalänk
Medlem
Skrivet av tufflax:

Uppdaterade mitt svar ovan.

Jag ritade 3 rektanglar som alla skär varandra. Sen tänkte jag vad som skulle ske med din loop, och det blir fel. Du tar bort för mycket area.

Vad gick fel med polygon-metoden?

När jag väl hade en polygon så kunde jag inte lösa hur ajg skulle beräkna arean av den. De metoder jag kunde hitta (t.ex getBounds()) gav en rektangel där polygonen kunde vara i. Efter någon timme återgick jag till rektanglar.

Men framför allt visste jag inte hur jag skulle göra en polygon, då skapandet av polygonen kräver points, och det har jag ju ingen aning om var de hamnar.

Intressant att den tar bort för mycket area, jag tänkte på det när jag gjorde forlooparna och kom fram till att alla areor jämförs med varandra bara en gång, därmed bör den inte ha tagit bort för mycket area. Tydligen hade jag fel?

Permalänk
Medlem
Skrivet av dovas92:

När jag väl hade en polygon så kunde jag inte lösa hur ajg skulle beräkna arean av den. De metoder jag kunde hitta (t.ex getBounds()) gav en rektangel där polygonen kunde vara i. Efter någon timme återgick jag till rektanglar.

Intressant att den tar bort för mycket area, jag tänkte på det när jag gjorde forlooparna och kom fram till att alla areor jämförs med varandra bara en gång, därmed bör den inte ha tagit bort för mycket area. Tydligen hade jag fel?

När du har en polygon får du göra algoritmen som stod på den där sidan.

Gör följande: Rita 3 reklanglar på ett papper, där varje rektangel har en del som skär ingen annan, 1 annnan, och 2 andra: dvs alla "fall" finns med. Sen ser du vad som händer med din loop. Den area som är snittet av alla 3 tas bort en gång för mycket. Den tas bort när 1 och 2 jämförs, när 1 och 3 jämförs, och när 2 och 3 jämförs. Men det var ju bara 3 rektanglar, så nu har den tagits bort lika många gånger som den las till.

Permalänk
Medlem
Skrivet av tufflax:

När du har en polygon får du göra algoritmen som stod gå den där sidan.

Gör följande: Rita 3 reklanglar på ett papper, där varje rektangel har en del som skär ingen annan, 1 annnan, och 2 andra: dvs alla "fall" finns med. Sen ser du vad som händer med din loop. Den area som är snittet av alla 3 tas bort en gång för mycket. Den tas bort när 1 och 2 jämförs, när 1 och 3 jämförs, och när 2 och 3 jämförs. Men det var ju bara 3 rektanglar, så nu har den tagits bort lika många gånger som den las till.

Problemet med polygoner var "points" också, där man kan lägga till points, men jag har ingen aning om vad som händer om man lägger till en points som redan finns innanför polygonen etc, det var så mycket att tänka på att jag gav upp.

Ja, du har rätt......vette fan om det går att lösa, måste kanske återgå till en polygon ändå

Permalänk
Medlem
Skrivet av dovas92:

Problemet med polygoner var "points" också, där man kan lägga till points, men jag har ingen aning om vad som händer om man lägger till en points som redan finns innanför polygonen etc, det var så mycket att tänka på att jag gav upp.

Ja, du har rätt......vette fan om det går att lösa, måste kanske återgå till en polygon ändå

Jag vet hur man löster det. http://en.wikipedia.org/wiki/Inclusion%E2%80%93exclusion_prin... Fast detta kommer inte funka, det kommer att gå för långsamt! Ge upp den här lösningen.

Jag fattar inte riktigt vad du menar med "points".

Permalänk
Medlem

Jag har tänkt lite mer, och jag tror att du måste använda nån typ av polygonmetod.

Permalänk
Hedersmedlem

Jag hittade följande post på StackOverflow.
http://stackoverflow.com/questions/2263272/how-to-calculate-t...

Jag ser inte hur du ska kunna loopa igenom en lista av rektanglar och lätt hitta arean. Om du vill lägga till en ny rektangel och utöka den totala arean så kanske 50% av din nya rektangel överlappas av en annan som redan finns i din lista och 50% av en annan. Men du måste dessutom veta hur mycket dessa två överlappar inbördes.

Visa signatur

Använd gilla för att markera nyttiga inlägg!

Permalänk
Medlem
Skrivet av tufflax:

Jag har tänkt lite mer, och jag tror att du måste använda nån typ av polygonmetod.

Eftersom det i detta fall handlar om diskret matematik så består varje rektangel av en uppräkningsbar mängd punkter, vilket gör att min tidigare givna lösning torde vara bland de enklare sätten att lösa det på.

Ponera att vi har följande rektanglar:
R1: (0,0)->(4,4)
R2: (1,1)->(5,5)
R3: (2,2)->(3,6)

Vi kan då lätt räkna ut vilka punkter respektive rektangel täcker (en loop i en loop genererar dessa med lätthet):
R1: (0,0)(0,1)(0,2)(0,3)(0,4)(1,0)(1,1)(1,2)(1,3)(1,4)(2,0)(2,1)(2,2)(2,3)(2,4)(3,0)(3,1)(3,2)(3,3)(3,4)(4,0)(4,1)(4,2)(4,3)(4,4)
R2: (1,1)(1,2)(1,3)(1,4)(1,5)(2,1)(2,2)(2,3)(2,4)(2,5)(3,1)(3,2)(3,3)(3,4)(3,5)(4,1)(4,2)(4,3)(4,4)(4,5)(5,1)(5,2)(5,3)(5,4)(5,5)
R3: (2,2)(2,3)(2,4)(2,5)(2,6)(3,2)(3,3)(3,4)(3,5)(3,6)

Om alla dessa punkter samlas i en lista som ej tillåter dubbletter, så kommer listans längd ge antalet punkter som är täckta.

Visa signatur

Laptop: Dell Latitude E7270 | 12,5" FHD IPS | i5-6300U | 16GB RAM | 500GB SSD
Laptop: MacBook Air 13"
NUC: Intel i5-4250U | 8GB RAM | 250GB SSD

Permalänk
Hedersmedlem
Skrivet av dovas92:

Hej alla swecs!

Jag har en sista övning kvar i en kurs, och jag förstår helt enkelt inte vad jag ska göra. Jag vet att det inte är meningen att man ska få kod via Sweclockers, men jag har nu suttit med detta i 4-5 timmar och kommer inte ens fram till hur jag ska börja.

Såhär ser uppgiften ut:

Allt eftersom man öppnar fler och fler fönster täcker dessa allt större yta av skärmen. Frågan är nu: Exakt hur stor yta täcker fönstren? Detta är inte trivialt att räkna ut eftersom fönster kan överlappa varandra helt eller delvis, som på bilden nedan.

Denna uppgift går ut på att, givet storlekarna på alla fönster, räkna ut hur många pixel2 fönstren tillsammans täcker på skärmen.

Indata inleds med ett heltal n, som anger antalet fönster. Därefter följer n rader med beskrivningar av fönstrens storlek. Varje sådan rad innehåller fyra tal, x1, y1, x2 och y2, där (x1,y1) är koordinaterna för fönstrets nedre vänstra hörn, och (x2,y2) är koordinaterna för fönstrets övre högra hörn. Du kan förutsätta att 1≤n≤1000, att alla koordinater är mellan 0 och 10000 (inklusivt), samt att x1<x2 och y1<y2.

Utdata ska bestå av ett enda heltal som anger arean på den yta av skärmen som täcks av fönster.

Jag har tänkt på dessa metoder: Beräkna totalarean och sedan subtrahera med samtliga täckande areor dvs. se det hela som rektanglar som "staplas", eller beräkna min X + max X och gå därifrån, försöka ta reda på "noderna" där riktningen ändras i 2D-stil.

Jag uppskattar varenda liten knuff jag kan få, jag har suttit och ritat på ett x antal papper och jag är helt slut i huvudet!

Har du någon känd lista att testa med?

Visa signatur

Använd gilla för att markera nyttiga inlägg!

Permalänk
Medlem
Skrivet av PeCe:

Eftersom det i detta fall handlar om diskret matematik så består varje rektangel av en uppräkningsbar mängd punkter, vilket gör att min tidigare givna lösning torde vara bland de enklare sätten att lösa det på.

Jo, iofs är det ganska enkelt. Men det kan också gå väldigt långsamt. Jag ignorerade metoden för den känns så himla ineffektiv.

Permalänk
Medlem

Enklast är att bryta ner problemet i två delar, en del som avgör hur många pixlar som rektanglarna överlappar på en rad, och sen bara loppa över alla rader.
Rektanglarna bildar en eller flera intervall, och antalet pixlar som täcks på en rad är summan av längden av dessa intervall. Två intervall som överlappas slås samman till ett enda intervall.

Visa signatur

Intel Core i7-3770K | NVIDIA Geforce GTX 980 | 16 GB DDR3 | DELL P2415Q | DELL U2711 | DELL U2410