Just nu i M3-nätverket
Gå till innehåll

Rotation av figur i koordinatsystem?


fredand

Rekommendera Poster

Hej igen!

 

Tack för all svar då jag frågat om formel för förstoring av area i ett koordinatsystem. Det är dock ej helt löst ännu, men jag kom på en fråga till som jag hoppas kunna få lite hjälp med.

 

Antag att man har en figur i ett koordinatsystem, t ex en barabapappa eller en fyrkant. Den ligger inte centrerad runt origo.

 

Problemet är att jag måste räkna ut figurens nya koordinater om den roteras runt sin egen axel med tc 30 grader.

 

Jag har kämpat men löser det inte. Jag är 32 år och har inte sysslat med trigonometri sen gymnasiet så jag har glömt en del.

 

Jag trodde att detta skulle funka men inte då:

x = x-cos(alfa)

y = y +sin(alfa)

 

Men detta flyttade hela figuren i en cirkelrörelse.

 

Så om någon kan hjälpa mig vore jag tacksam

 

Stort tack på förhand

Fredrik

 

[bild bifogad 2005-07-03 20:06:00 av fredand]

726049_thumb.jpg

Länk till kommentar
Dela på andra webbplatser

OBS jag har bifogat en bild som jag hoppas illustrerar problemet i förra inlägget i denna tråd.

 

Mvh

Fredrik

 

Länk till kommentar
Dela på andra webbplatser

Du måste väl bestämma mittpunkten i figuren och en punkt i figuren som du ändrar vinkeln till och utifrån den nya positionen ritar ut de andra punkterna.

 

 

°±°

 

Länk till kommentar
Dela på andra webbplatser

Hej,

 

Räkna ut en mittpunkt i figuren på något sätt, tex som medelvärdet av det största och minsta respektive x-värdet och y-värdet:

cx = (xmax-xmin)/2

cy = (ymax-ymin)/2.

 

Nu kan alla punkter beskrivas som (x, y), eller (a, l) enligt PerboMans formel i din tidigare tråd. Det senare sättet, med en radie (l) och en vinkel (a) kallas också polära koordinater. Basplanet läggs vanligtvis parallellt med x-axeln (se bifogad figur). Några omvandlingsformler:

 

dx = x - cx <=> x = dx + cx

dy = y - cy <=> y = dy +cy

 

l = sqrt(dx^2+dy^2)

a = arccos(dx/l) = arcsin(dy/l) = arctan (dy/dx)

cos(a) = dx/l <=> dx = cos(a)*l

sin(a) = dy/l <=> dy = sin(a)*l

 

För att ändra storlek på din figur ändrar du radien (l) med samma faktor för alla punkter. För att rotera figuren ändrar du vinkeln (a) med samma värde för alla punkter. Både stoleksändring och rotation sker relativt mittpunkten (cx, cy), som alltså aldrig flyttas.

 

mvh

/Johan

 

[bild bifogad 2005-07-03 20:59:07 av Pejo]

726057_thumb.jpg

Länk till kommentar
Dela på andra webbplatser

Tjenis!

 

Tack för ditt svar!

 

Jag får det dock inte att funka riktigt om jag förstått dig rätt.

 

(Se bifogad bild, önskan är dock att det ska funka för "barbapappa" areor också och inte bara kvadrater)

 

Jag gör så här:

 

0) koordinaterna för denna fyrkant ser ut så här:

-40,-40

-20,-40

-20,-20

-40,-20

 

1) Räknar ut en centrumpunkt genom att leta rätt på min och max:

cx = ((xMax - xMin)/2) + xMin

cy = ((yMax - yMin)/2) + yMin

 

2) Räknar ut differenserna för varje koordinats x och y värde (hoppas att jag fattat detta rätt)

DiffVärde = (Värde - CentrumVärde)

Diff x: -10.0 (-40--30.0) diff y: -10.0 (-40--30.0)

Diff x: 10.0 (-20--30.0) diff y: -10.0 (-40--30.0)

Diff x: 10.0 (-20--30.0) diff y: 10.0 (-20--30.0)

Diff x: -10.0 (-40--30.0) diff y: 10.0 (-20--30.0)

 

3) Räknar ut radien för varje koordinat dvs längden mellan centrum till nuvarande punkter:

(I denna kvadrat blir den ju den samma dock)

radie = sqrt(diffx*diffx + diffy*diffy):

14.142136

14.142136

14.142136

14.142136

Värdena känns trovärdiga så jag tror jag gjort rätt.

 

4) Räknar ut de nya koordinaterna med vinkeln 1 grad:

x = cos(1) * radius

y = sin(1) * radius

detta gav dessa nya avrundada värden, samma då radien är den samma:

8,12

8,12

8,12

8,12

 

Jag antar att de på något vis ska appliceras på orginalkoordinatera nu, men varken + eller - verkar göra något vettigt då arean ska roteras runt koordinaten -30,-30.

 

Då jag adderade de nya värdena till de gamla hoppade bara koordinaten lite snett till höger, som ni ser på bilden.

 

Ser ni vad jag gör för fel?

 

Stort tack på förhand

Fredrik

 

Länk till kommentar
Dela på andra webbplatser

Hej!

 

Det jag ska göra är att räkna ut kordinaten C på nedanstående sidas första bild av enhetscirkeln:

 

http://matmin.kevius.com/trigonometri.html

 

Enligt tidigare beräkninagr tycker jag att jag känner till:

vinkeln: 1 grad

Koordinaten A och kan då räkna ut basen.

 

Så om någon kan räta ut frågetecknet så vore det toppen.

 

Mvh

Fredrik

 

 

 

Länk till kommentar
Dela på andra webbplatser

Gick lite fort det där ...

 

1) Min uträkning av mittpunkten ska vara:

cx = (xmax+xmin)/2

cy = (ymax+ymin)/2

dvs med '+' istället för '-', men det ger samma resultat som din uträkning.

 

4) Du behöver en vinkel (a) till varje punkt för att skriva om den i polära koordinater.

(x, y) = (cx+l*cos(a), cy+l*sin(a))

Kom inte riktigt i mål där i mitt förra inlägg ...

cos(a) = dx/l <=> a = arccos(dx/l),

men arccos skiljer inte på punkter över och under x-axeln, varför följande justering behövs:

om dy>0: a = arccos(dx/l)

annars: a = 2*pi-arccos(dx/l)

Vanligtvis anges a i radianer (360 grader = 2*pi radianer), men det kan bero på implementeringen av cos() och arccos().

 

Nu till omformningen.

För att vrida figuren, öka a med samma värde för alla punkter:

a <- a+da

För att skala storleken, öka l med samma faktor för alla punkter:

l <- l*dl

dvs, flyttad punkt (x, y) ges av (cx+l*dl*cos(a+da), cy+l*dl*sin(a+da))

De båda operationerna kan naturligtvis utföras samtidigt.

 

mvh

/Johan

 

Länk till kommentar
Dela på andra webbplatser

Hej igen!

 

Detta ser mycket intressant ut.

 

Jag antar att då jag har följande utgångsdata att använda:

ursprungskoordinater

rotationsvinkeln diffAlfa jag hittar på själv, t ex 1 grad

 

Så måste jag göra så här:

 

1) Räkna ut koordinaten cx,cy som förut

 

2) Räkna ut samtliga vinklar för alla kordinater i förhållande till cx, cy?

Jag antar att jag gör det så här:

2a) Räkna ut alla radier (l) för alla nuvarande koordinater

2b) Vinkeln alfa för varje nuvarnde koordinat fås sedan genom:????

Vänta nu eee hmm:

diffx/radien = arccos(alfa)

Fast hur får jag fram vinkelmåtet i grader?? Får jag det genom inventering om jag minns rätt? Dvs 1/arccos(alfa) ???

 

3) Räkna ut nya vridna koordinater med vinkeln diffAlfa + alfa för varje koordinat:

(x, y) = (cx+radien*cos(diffAlfa + alfa ), cy+radien*sin(diffAlfa + alfa ))

 

Borde detta bli rätt för rotationen?

 

Mvh

Fredrik

 

PS då jag fattat detta borde jag ju enkelt fatta förstoringen också med din mycket pedagogiska förklaring.

 

Jag återkommer under kvällen, men kommenterar gärna mina frågetecken på steg 2.

 

 

 

 

Länk till kommentar
Dela på andra webbplatser

2) Räkna ut samtliga vinklar för alla kordinater i förhållande till cx, cy?

Japp. Generellt behövs två värden för att ange läget av en punkt i ett 2-dimensionellt koordinatsystem. Antingen (x, y), som refererar till axlarna, eller (radie, vinkel) som relaterar till origo. I detta fall väljer vi en annan "startpunkt" (cx, cy) för de polära koordinaterna.

 

Att byta koordinatsystem är ett vanligt trick för att förenkla formler och beräkningar inom matematik och fysik. Du har en figur som är angiven med x-y-koordinater och vill rotera och skala den. Båda dessa operationer är lätta att utföra i polära koordinater varför det är vettigt med följande gång:

 

1) (x,y) -> (polära koordinater)

2) Ändra de polära koordinaterna.

3) (polära koordinater) -> (x, y)

 

Steg 2) och 3) kan slås ihop enligt

(cx+l*dl*cos(a+da), cy+l*dl*sin(a+da))

 

Steg 1) innebär att hitta radien (l) och vinkeln (a) för respektive punkt. Radien ges av Pythagoras sats (l^2=dx^2+dy^2) och vinkeln genom funktionen arccos(), vilken är inversen till cos().

a = arccos(dx/l)

Problemet är att arccos inte säger allt, varför följande lilla trick behövs för att hitta a för punkter hela varvet runt (cx, cy):

om dy=>0: a = arccos(dx/l)

annars: a = 2*pi-arccos(dx/l)

 

Angående grader och radianer:

 

grader = 360*radianer/(2*pi) = radianer*180/pi

radianer = pi/180*grader

 

mvh

/Johan

 

Länk till kommentar
Dela på andra webbplatser

Hejsan!

 

(SE BIFOGAD BILD)

 

Jag tror jag äntligen fått det att funka.

 

Jag kanske måste nämna att jag pysslar lite med ett mindre Java-program där man ska kunna rita figurer i ett kordinat system.

 

Därmed är jag begränsad till pixlar, dvs heltal på alla koordinater.

 

Det jag nu fått fenomenal hjälp med av dig verkar fungera bra på rektanglar. När figuren är en "barabapappa" blir det värre.

 

Jag antar att det har att göra med avrundningen jag tvingas göra på slutet.

 

Jag försöker beskriva hur jag gör nedan, så misstänker du att jag gör något fel så hojta gärna:

 

1) I decimal tal tar jag fram cx och cy

2) Hitta alla diff mellan centerX och X och centerY och Y också i decimaltal

3) Hitta alla radier med pytagoras-sats

4) Hitta alla vinklar, först i cos form som sen omvandlas i radianer-form med arccos så här:

if(Ydiff> 0)

{

angle = (Math.acos(Ydiff/radie) * dir);

}

else

{

angle = ( (2*Math.PI) - Math.acos(Ydiff/radie) * dir);

}

 

5) Räkna ut alla nya koordinater (double = decimal i Java). Jag vrider med 5 grader varje gång:

double cos = (radie * Math.cos(angle + ((2*Math.PI)/72)) );

double sin = (radie * Math.sin(angles + ((2*Math.PI)/72)) );

 

Slutlig nya kordinat:

nyX = Math.round(Math.round(centerX + cos));

nyY = Math.round(Math.round(centerY + sin))

 

Hoppas du förstår mina tankegångar i Java-kod.

 

Så om du tror deformationen på bilen beror på annat än avrundningen på slutet får du gärna hojta till igen.

 

Stort tack på förhand

 

Fredrik

 

[bild bifogad 2005-07-04 21:37:22 av fredand]

[inlägget ändrat 2005-07-04 21:38:16 av fredand]

726419_thumb.jpg

Länk till kommentar
Dela på andra webbplatser

Math.acos(Ydiff/radie) * dir

Byt Ydiff mot Xdiff (eller vad du nu kallar dx) i båda acos() uttrycken. (Vad gör dir?)

 

double sin = (radie * Math.sin(angles + ((2*Math.PI)/72)) );

angles -> angle ?

 

/Johan

 

Länk till kommentar
Dela på andra webbplatser

Hej!

 

Tack för ditt svar!

 

Tyvärr hade jag skrivit fel i inlägget, då jag ser att jag verkligen körde:

 

if(Ydiff> 0)

{

angle = (Math.acos(dx/radie) * dir);

}

else

{

angle = ( (2*Math.PI) - Math.acos(dx/radie) * dir);

}

 

Längre ned hade jag också slarvat då jag förskte översätta min kod till mer förstålig matematik:

angles är samma som angle.

 

(Om du vill veta sparar jag allt i sk listor/arrayer där av s:et för plural i namnet)

 

Så det skumma är att det blir en deformation av figuren under roteringen av en mer komplex figur än t ex en kvadrat. Jag ska se om jag kan avrunda på ett bättre sätt. Buggen är att varje koordinat är en pixel så jag kan ju inte ha några decimaler.

 

Tror du att det kan vara avrundning till heltal som ger detta?

 

Mvh

Fredrik

 

 

Länk till kommentar
Dela på andra webbplatser

Glömde tala om att variabeln "dir" är till för riktningen på vridningen och är antingen 1 eller -1, just nu endast 1.

 

Mvh

Fredrik

 

Länk till kommentar
Dela på andra webbplatser

OK.

 

För att minimera antalet beräkningar (och därmed avrundningsfel) kan vi skriva om uttrycken för (x, y) med hjälp av lite trigonometriska formler. Slutresultatet blir hela omformningen (Xn, Yn) -> (Xn+1, Yn+1) i ett steg:

 

Xn+1 = Xc+dl*[(Xn-Xc)*cos(da) - (Yn-Yc)*sin(da)]

Yn+1 = Yc +dl*[(Xn-Xc)*sin(da) + (Yn-Yc)*cos(da)]

 

Kompaktare än så tror jag inte att det får att gå ... (Detta är detsamma som rotationsmatrisen som nämndes i ett tidigare inlägg.)

 

Behåll du (Xc, Yc) som heltal, dom är bara en approximation av figurens mittpunkt och deras exakta värde spelar inte så stor roll.

 

Om du vill skilja på riktning och steg bör båda ingå i da, dvs da = dir * step.

 

mvh

/Johan

 

Länk till kommentar
Dela på andra webbplatser

Hej!

 

Tack för ditt svar!

 

Jag har försökt att översätta din sista formel men jag åker på en ofrivillig förstoring, se bild:

http://www.dsv.su.se/~fr-ander/rot.GIF

 

Jag har gjort så här:

Xn+1 = Xc+dl*[(Xn-Xc)*cos(da) - (Yn-Yc)*sin(da)]

Yn+1 = Yc+dl*[(Xn-Xc)*sin(da) + (Yn-Yc)*cos(da)]

 

Där

Xn+1 = den nya x koordinaten

Yn+1 = den nya y koordinaten

 

Xc = centrum X

Yc = centrum Y

 

dl = radien mellan Xc, Xy och nuvarande X,Y

 

Xn = nuvarande X

Yn = nuvarande Y

 

da = (2*Math.PI)/72)*dir = 5 grader * (-/+)

 

Vad tror du är buggen?

 

Mvh

Fredrik

 

Oerhört stort tack på förhand

Fredrik

 

Länk till kommentar
Dela på andra webbplatser

Kompaktare än så tror jag inte att det får att gå
Man kan ju lägga ut beräkningen av cos(da) och sin(da) innan formeln så beräknas dessa bara en gång istället för två...

 

 

°±°

 

Länk till kommentar
Dela på andra webbplatser

dl = radien mellan Xc, Xy och nuvarande X,Y

 

'dl' är bara skalfaktorn och 'l' behöver inte beräknas alls (försvann i omskrivningen av formeln). Om du inte ändrar storlek är dl=1 och kan utelämnas helt.

 

mvh

/Johan

 

Länk till kommentar
Dela på andra webbplatser

Naturligtvis, för minsta möjliga antal beräkningar bör även Xn-Xc och Yn-Yc bara göras en gång. Med kompaktare avsåg jag närmast antalet variabler och mellansteg, men så har jag aldrig sett mig som någon riktig programmerare heller ... :)

 

mvh

/Johan

 

[inlägget ändrat 2005-07-05 12:07:17 av Pejo]

Länk till kommentar
Dela på andra webbplatser

Hej!

 

Tack för hjälpen!

 

Nu funkar den nya formeln som innan, dvs jag kan rotera en kvadrat eller en rektangel utan problem.

 

Tyvärr blir andra figurer typ en "barbapappa" deformerad.

 

Jag kan tänka mig att det beror på:

 

1) Avrundningar till heltal eftersom en pixel är ett heltal.

 

2) Kanske beror det på just vinkeln 5 grader (2*Math.PI)/72). Kanske går det att hitta en universalvinkel som är bättre?

 

3) Kanske beror det på att min cx, cy inte är korrekt. Jag räknade fram denna så här:

cx = ((xMax - xMin)/2) + xMin;

cy = ((yMax - yMin)/2) + yMin;

Testade även med din tjusigare som dock gav samma resultat.

cx = (xMax+xMin)/2;

cy = (yMax+yMin)/2;

Kan det vara så att detta medelvärde inte är korrekt?

 

Men jag tror ni är inne på, som jag, att det måste bero på avrundningar?

 

Jag bifogar än bild som visar en deformering.

 

http://www.dsv.su.se/~fr-ander/rot1.GIF

 

Dessa är koordinaterna från start:

-40:-20

-40:-40

-20:-40

-10:-30

-5:-20

-5:-5

-20:-5

-30:-10

-40:-20

 

Dessa är kordinaterna efter rotering 36 gånger a 5 grader ((2*Math.PI)/72) (180 grader totalt)

-8:-32

-6:-4

-19:-6

-31:-11

-38:-18

-40:-42

-25:-40

-19:-37

-8:-32

 

Som ni ser, ser ju figuren lite deformerad ut nu. Och värre blir det för varje vidare vridning.

 

Jag testade även att endast vrida med 180 grader 1 gång (Math.PI), koordinater från början:

-40:-20

-40:-40

-20:-40

-10:-30

-5:-20

-5:-5

-20:-5

-30:-10

-40:-20

 

Dessa är koordinaterna nu:

-4:-20

-2:-40

-22:-40

-33:-30

-39:-20

-40:-5

-25:-5

-15:-10

-4:-20

 

Det ser bättre ut Så det borde ju tyda på att det handlar om avrundning kort och gott.

 

Eller vad tror ni?

 

Stort tack på förhand

Fredrik

 

Länk till kommentar
Dela på andra webbplatser

Det ser bättre ut Så det borde ju tyda på att det handlar om avrundning kort och gott.

Verkar troligt. Om figuren inte är större än 40x40 punkter märks förmodligen en pixel hit eller dit efter 36 rotationer. Hoppas att detta inte sänker din idé helt och hållet, men om inte annat har både du och jag fått en uppfriskning av lite elementär geometri. :)

 

mvh

/Johan

 

Edit: Kom på en sak till ... Som jag sa tidigare borde inte det exakta värdet av (Xc, Yc) spela så stor roll, åtminstone inte för varje ENSTAKA vridning. Om du alltid gör ett gäng smårotationer i ett svep finns det ingen anledning att räkna om "mittpunkten" för varje liten rotation (om du nu gör det). Använd istället samma mittpunkt för ett objekt vid alla ändringar.

[inlägget ändrat 2005-07-05 16:38:04 av Pejo]

Länk till kommentar
Dela på andra webbplatser

Tjenis!

 

Jag har hackat på mitt figur-program efter att jag fick svar från dig angående att cx, cy inte behövdes räknas om.

 

Så nu är jag äntligen klar med det.

 

Helt klart är att resultatet är betydligt bättre med en konstant cx,cy!

 

Men en viss deformation verkar jag få ändå, men inte alls lika som innan.

 

Jag måste be att få tacka för all din hjälp med detta, du är verkligen duktig på matematik. Skulle du ge dig på programmering, om jag förstod rätt så håller du inte på med det, så skulle du gå väldigt väldigt långt.

 

Tusen tack för hjälpen!

 

Kanske frågar jag dig igen då jag tänkte använda samma formel för förstoringen. Jag har inte helt fått till det heller.

 

Mvh

Fredrik

 

Länk till kommentar
Dela på andra webbplatser

Så nu är jag äntligen klar med det.

Helt klart är att resultatet är betydligt bättre med en konstant cx,cy!

Hoppas att det blev som du tänkte.

 

Jag måste be att få tacka för all din hjälp med detta, du är verkligen duktig på matematik.

Duktig och duktig, ett och annat fastnade tydligen under mina chalmers-år trots allt, även om det var ett tag sedan.

 

Skulle du ge dig på programmering, om jag förstod rätt så håller du inte på med det, så skulle du gå väldigt väldigt långt.

Under utbildningen tog jag de obligatoriska grundkurserna (i ett nu utdött språk) och nog fuskar jag lite till från med enklare programmering (typ skript och VBA), men jag är glad om jag slipper programmera för mitt uppehälle då jag har en tendens att gräva ner mig fullständigt i jakten på den perfekta koden.

 

mvh

/Johan

 

Länk till kommentar
Dela på andra webbplatser

Tjenis!

 

Jag kom på att jag för varje rotation även räknar om:

xDiff, yDiff

radien för varje koordinat

vinkeln för varje koordinat

 

Tror du att jag kanske skulle ta och låta bli det och behålla:

xDiff, yDiff

radien för varje koordinat

...från urspungs läget???

 

Vad tror du?

 

Stort tack på förhand!

 

Mvh Fredrik

 

[inlägget ändrat 2005-07-07 14:19:00 av fredand]

Länk till kommentar
Dela på andra webbplatser

Arkiverat

Det här ämnet är nu arkiverat och är stängt för ytterligare svar.

×
×
  • Skapa nytt...