Hankala kysymys...

Voit pyytää apua ohjelmointiongelmiin täältä.
Post Reply
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Hankala kysymys...

Post by MaGetzUb »

Noh, tarttisin apua sellaaseen funktioon joka tarkastaisi nopeasti onko pallo mennyt viivan yli, samoin kuin LineIntersect:issä tarkistetaan onko viiva mennyt
toisen yli... LineIntersectistä sain tehtyä sellaasen, että onko pikseli mennyt viivaan, mutta en sellaasta, että onko pallo osunut viivaan...
Apua ja funktiota kaivataan! :P :D
Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.
Kassu
Newcomer
Posts: 22
Joined: Wed Aug 29, 2007 5:32 pm

Re: Hankala kysymys...

Post by Kassu »

Siis haluatko tarkistaa jos pallo on mennyt viivan yli vai jos see on osunut siihen?
Jos haluat tarkistaa onko pallo on mennyt viivan yli, niin se hän on periaatteessa sama asia kuin jos pallon vanhojen ja uusien kordinaattien välinen viiva on ylittänyt kyseisen viivan yli.
SPuntte
Tech Developer
Tech Developer
Posts: 650
Joined: Mon Aug 27, 2007 9:51 pm
Location: Helsinki, Finland
Contact:

Re: Hankala kysymys...

Post by SPuntte »

programmer of DSG wrote:Noh, tarttisin apua sellaaseen funktioon joka tarkastaisi nopeasti onko pallo mennyt viivan yli, samoin kuin LineIntersect:issä tarkistetaan onko viiva mennyt
toisen yli... LineIntersectistä sain tehtyä sellaasen, että onko pikseli mennyt viivaan, mutta en sellaasta, että onko pallo osunut viivaan...
Apua ja funktiota kaivataan! :P :D
Jos ympyrä on kulkenut janan yli, jana, joka on piirretty ympyrän (keskipisteen) entisestä sijainnista nykyiseen, leikkaa alkuperäisen janan.

Jos taas haluat tietää, leikkaako ympyrä janan, siihen täytyy soveltaa kaavaa, joka kertoo pisteen etäisyyden suorasta, kun piste ja suoran yhtälö tunnetaan. Kerro ensin tarkoititko tätä, niin autan sitten vasta, koska en nyt jaksa alkaa turhan takia yhtälöitä pyörittelemaan
EDIT:

Njahah.. NorthBurns muisti vielä sen, että kyseessä oli jana. Epäilen vaan suuresti, onnistuuko tuon kääntäminen funktioksikaan, jos on vaikeuksia realisoida se, mitä funktion pitäisi tehdä. Lisäksi vektorit ja janan yhtälö eivät ole mitään ihan yläastekamaa..

Last edited by SPuntte on Fri Feb 22, 2008 11:47 pm, edited 2 times in total.
CoolBasic henkilökuntaa
Tech-kehittäjä
CoolBasic Classic, Cool VES

CoolPhysicsEngine | MissileSystem | Jana-ympyrä -törmäys | cbSimpleTexture | CoolCPLX
Northburns
Newcomer
Posts: 7
Joined: Tue Aug 28, 2007 5:49 pm

Re: Hankala kysymys...

Post by Northburns »

Joo, tuollaisen ympyrä-jana-leikkaus -funktion tekeminen ei ole ihan pala kakkua, olettaen että siitä haluaa tehokkaan. Mutta pienellä vektorien pyörittelyllä pystyy tekemään funktion, joka ei turvaudu trigonometriaan, tai muuhunkaan hömppään.
En viitsi kirjoittaa valmista funktiota sinulle, mutta sen sijaan kirjoitin pienen tekstin, jonka kun lukaiset, saat tehtyä itse funktiosi ja saatat jopa tajuta mitä se tekee :)
Helpotan kuitenkin luku-urakkaasi merkitsemällä tähdellä rivit, jotka saapuvat funktioosi asti.

Code: Select all

*Jos käsiteltävänä on jana (pisteestä P1 pisteeseen P3) ja ympyrä (keskipiste P3, säde r), mieti seuraavaa:

Ympyrää lähin piste janalla on [u]janan[/u] ja [u]janaa kohtisuorassa olevan ja P3:n läpi kulkeva suoran[/u] leikkauspiste. Merkitään leikkauspistettä P:llä.

Otetaan jana P3-P (suorasta pätkä) ja "alku-"jana P2-P1. Näiden vektorien pistetulo on nolla, jos ne ovat kohtisuorassa:
	(P3-P) dot (P2-P1) = 0
Kun tähän sijoitetaan janan yhtälö, P = P1 + u*(P2-P1), saadaan:
	(P3-P1-u*(P2-P1)) dot (P2-P1) = 0
Kun tästä ratkaistaan u (janan yhtälön parametri), saadaan:
        (x3-x1)(x2-x1)+(y3-y1)(y2-y1)
*   u = -----------------------------
        (x2-x1)(x2-x1)+(y2-y1)(y2-y1)
*Jos u on jotain 0:n ja 1:n välillä, on ympyrää lähinnä oleva piste janalla!

*Seuraavaksi täytyy selvittää, onko piste P alle säteen päässä ympyrän keskipisteestä. Tosi: törmäys, Epätosi: ei tormäystä.

Tiedämme jo pisteen P, parametrin u avulla:
	P = P1 + u*(P2-P1)
Ja tiedämme ympyrän keskipisteen P3. Törmäysehto saadaan muotoon:
	| P3-P | < r
Komponentit auki:
	sqrt( (x3-x1-u*x2+u*x1)^2 + (y3-y1-u*y2+u*y1)^2 ) < r
Korotetaan epäyhtälö toiseen potenssiin (koska neliöjuuret ovat hitaita) ja järjestellään termit nätimmin:
*	(x3-x1+u*(x1-x2))^2 + (y3-y1+u*(y1-y2))^2 < r^2



Leikkauspisteen/leikkauspisteiden ratkaiseminen jätetään harjoitukseksi lukijalle. 

Referenssinä käytetty: Laskin ja http://local.wasp.uwa.edu.au/~pbourke/geometry/sphereline/
SPuntte
Tech Developer
Tech Developer
Posts: 650
Joined: Mon Aug 27, 2007 9:51 pm
Location: Helsinki, Finland
Contact:

Re: Hankala kysymys...

Post by SPuntte »

BUHHAHHAH.

Nyt olen kerrassaan ilkeä ihminen. Kiinnostuin jostain kumman syystä itse tästä aiheesta ja käytin siihen aikaa, joten en voi vastustaa kiusausta hieman egottaa, että osaanpahan minäkin matikkaa. Ensinnäkin teen Northburns'n vaivannäön turhaksi ja toiseksi pilaan programmer of DSG'n oppimisen ilon sekä sekoitan samalla hänen päätänsä vähän lisää. :mrgreen:

Anteeksi jo etukäteen.

Tarvitsin tähän ainoastaan MAOL'a sekä kynän ja paperia, jotta sain vähän purettua kaavoja koodikelpoisiksi. Jostain syystä kommentoin kaiken englanniksi.. Lineekö siitä mitään hyötyä, kun ei täällä juuri muita kuin suomalaisia liiku.

Funktiot toimivat seuraavasti:

PointInLineSegArea:
Tarkistaa onko annettu piste janan päätepisteiden kautta kulkevien normaalien rajaaman alueen sisäpuolella.

Matemaattisesti tämä toimii siten, että se tarkistaa, ovatko janavektorin ja sen vastavektorin sekä pisteen ja janan päätepisteiden välisten vektoreiden pistetulojen merkit samat. Jos ovat, piste on alueen sisällä.

PointToLineDist:
Laskee pisteen etäisyyden suorasta.

Ts. annetun pisteen ja sitä lähinnä suoralla sijaitsevan pisteen välisen vektorin/janan pituuden. Johdettu MAOL'n kaavoista (kahdeen pisteen kautta kulkevan suoran yhtälö, pisteen etäisyys suorasta; s. 43).

CircleToLineSegIsect:
Tarkistaa leikkaako ympyrä janan.

Jos ympyrän keskipiste toteuttaa ensimäisen funktion ja keskipisteen etäisyys janan päätepisteiden kautta kulkevasta suorasta on pienempi tai yhtäsuuri kuin ympyrän säde, tai vaihtoehtoisesti ympyrän keskipisteen etäisyys ainakin toisesta janan päätepisteestä on pienempi tai yhtäsuuri kuin ympyrän säde, leikkaus on tosi.

Khoodia(esimerkki sisältyy):

Code: Select all

Randomize Timer()
x1 = Rand(50, 350)
y1 = Rand(50, 250)
x2 = Rand(50, 350)
y2 = Rand(50, 250)
rad = Rand(20, 50)

ShowMouse OFF

Repeat
    Color 255, 255, 255
    Text 5, 5, "Mouse in 'segment area': " + PointInLineSegArea(MouseX(), MouseY(), x1, y1, x2, y2)
    Text 5, 17, "Point to Line -distance: " + PointToLineDist(MouseX(), MouseY(), x1, y1, x2, y2)
    Text 5, 29, "Circle to line segment intersection: " + CircleToLineSegIsect(MouseX(), MouseY(), rad, x1, y1, x2, y2)
    Text 5, 40, "Press space to re-randomize values"
    Line x1, y1, x2, y2
    
    Color 255, 0, 0
    Dot MouseX(), MouseY()
    Circle2(MouseX(), MouseY(), rad, OFF)
    
    If KeyHit(CBkeySpace) Then
        x1 = Rand(50, 350)
        y1 = Rand(50, 250)
        x2 = Rand(50, 350)
        y2 = Rand(50, 250)
        rad = Rand(10, 50)
    EndIf
    
    DrawScreen
Forever

//CircleToLineSegIsect
//
//Returns:
//  TRUE (1) when:
//      Circle [center=point (cx, cy); radius=r]
//      intersects Line through points (l1x, l1y) & (l2x, l2y)
//  FALSE (0) in every other cases
Function CircleToLineSegIsect(cx#, cy#, r#, l1x#, l1y#, l2x#, l2y#)
    //Circle center inside 'line segment area'
    If PointInLineSegArea(cx, cy, l1x, l1y, l2x, l2y) = True And PointToLineDist(cx, cy, l1x, l1y, l2x, l2y) <= r Then
        Return True
    //Circle center outside 'line segment area'
    ElseIf Distance(cx, cy, l1x, l1y) <= r Or Distance(cx, cy, l2x, l2y) <= r Then
        Return True
    Else
        Return False
    EndIf
EndFunction

//PointToLineDist
//
//Returns:
//  Distance between
//  Point (px, py)
//  and
//  Line through points (l1x, l1y) & (l2x, l2y)
Function PointToLineDist(px#, py#, l1x#, l1y#, l2x#, l2y#)
    //'Formula' of the line
    a# = (l2y - l1y) / (l2x - l1x)
    b# = -1
    c# = -(l2y - l1y) / (l2x - l1x) * l1x + l1y
    
    //Distance
    d# = Abs(a * px + b * py + c) / Sqrt(a * a + b * b)
    
    Return d
EndFunction

//PointInLineSegArea
//
//Returns:
//  TRUE (1) when:
//      point(px, py) appears in area
//      restricted by the normals of the line segment
//      drawn through the end points of the line segment
//
//  FALSE (0) in every other cases
Function PointInLineSegArea(px#, py#, l1x#, l1y#, l2x#, l2y#)
    //Vectors
    SegVecX# = l2x - l1x 
    SegVecY# = l2y - l1y
    
    PntVec1X# = px - l1x
    PntVec1Y# = py - l1y
    
    PntVec2X# = px - l2x
    PntVec2Y# = py - l2y
    
    //Dot products
    dp1# = SegVecX * PntVec1X + SegVecY * PntVec1Y
    dp2# = -SegVecX * PntVec2X - SegVecY * PntVec2Y
    
    //Checks if DPs' signs are same
    If dp1 = 0 Or dp2 = 0 Then
        Return True
    ElseIf Sign(dp1) = Sign(dp2) Then
        Return True
    Else
        Return False
    EndIf
EndFunction

Function Sign(val)
    If val > 0 Then
        Return 1
    ElseIf val < 0 Then
        Return -1
    Else
        Return 0
    EndIf
EndFunction

Function Circle2(x, y, r, fill=0)
    Circle x-r,y-r,r*2,fill
EndFunction
CoolBasic henkilökuntaa
Tech-kehittäjä
CoolBasic Classic, Cool VES

CoolPhysicsEngine | MissileSystem | Jana-ympyrä -törmäys | cbSimpleTexture | CoolCPLX
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Re: Hankala kysymys...

Post by MaGetzUb »

No huhhuh mitä soopaa (Minulle. Hyvä kun osaan laskea potensseja jotenkin.) :P ei millää pahalla. :)
Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.
SPuntte
Tech Developer
Tech Developer
Posts: 650
Joined: Mon Aug 27, 2007 9:51 pm
Location: Helsinki, Finland
Contact:

Re: Hankala kysymys...

Post by SPuntte »

Vähän sitä pelkäsin :P Jos tuosta funktioväkerryksestäni on jotain hyötyä, hyvä niin. Voisin yhdistää nuo kaikki yhdeksi funktioksi (joka siis tarkastaa, leikkaavatko ympyrä ja jana) mikä säästäisi CB:n funktiorajan ylittymistä ja selventäisi, kun tietäisit, että on yksi funktio ja se tarkastaa juuri sitä ja sitä.

Eihän yläasteella käytetä edes MAOL'a tai mitään muutakaan apuvälinettä funktiolaskimen lisäksi, vaan kaikki 'kaavat' opetellaan ulkoa :lol:
CoolBasic henkilökuntaa
Tech-kehittäjä
CoolBasic Classic, Cool VES

CoolPhysicsEngine | MissileSystem | Jana-ympyrä -törmäys | cbSimpleTexture | CoolCPLX
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Re: Hankala kysymys...

Post by MaGetzUb »

Sain itse tehtyy tallaase:

Code: Select all

Function CircleIntersect(Ax#, Ay#, Bx#, By#, Cx#, Cy#,size = 40)

For I = 0 To 72
If PixelIntersect(Ax#, Ay#, Bx#, By#,Cx#+Cos(i*5)*size,Cy#+Sin(i*5)*size) Then Return 1
Next i

EndFunction 

Function PixelIntersect(Ax#, Ay#, Bx#, By#, Cx#, Cy#)
Rn# = (Ay#-Cy#) - (Ax#-Cx#)
Rd# = (Bx#-Ax#)- (By#-Ay#)
If Rd# = 0
Return False
Else
Sn# = (Ay#-Cy#)*(Bx#-Ax#) - (Ax#-Cx#)*(By#-Ay#)
Intersection_AB# = Rn# / Rd#
Intersection_CD# = Sn# / Rd#
If Intersection_AB# > 1 Or Intersection_CD# > 1 Or Intersection_AB# < 0 Or Intersection_CD# < 0 Then Return False
IntersX = Ax# + Intersection_AB#*(Bx#-Ax#)
IntersY = Ay# + Intersection_AB#*(By#-Ay#)
Return True
EndIf
End Function
EDIT:

Se on harmi, ettei gosub:ia voi käyttää function sisällä. :(

Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Re: Hankala kysymys...

Post by MaGetzUb »

Anteeksi kaksois postaus, mutta piti vähän saada tänne taas eloa, koska toi Spunten Funktio on ihan toimiva. Eli voit Spuntte Pistää ne kaikki yhdeksi ja postata ne tänne. ;) Jos on aikaa ja halua.
Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.
SPuntte
Tech Developer
Tech Developer
Posts: 650
Joined: Mon Aug 27, 2007 9:51 pm
Location: Helsinki, Finland
Contact:

Re: Hankala kysymys...

Post by SPuntte »

Thäsää hän ois. Katsoin suunnilleen, että tuossa ei suoriteta mitään turhaan, eli järjestin tarkistukset yksinkertaisimmasta monimutkaisimpaan nin, että ensin tulevat sulkevat kaikki jälkimmäiset pois, mutta saatta sieltä vielä optimoinnin varaa löytyä. Tuo 2/3 tyhjä If..Elseif..Else rakenne jäi vähän vaivaamaan.. :?

Code: Select all

//CircleToLineSegIsect2
//
//Returns:
//  TRUE (1) when:
//      Circle [center=point (cx, cy); radius=r]
//      intersects Line through points (l1x, l1y) & (l2x, l2y)
//  FALSE (0) in every other cases
Function CircleToLineSegIsect2(cx#, cy#, r#, l1x#, l1y#, l2x#, l2y#)
    //Circle center Near enough the end points
    If Distance(cx, cy, l1x, l1y) <= r Or Distance(cx, cy, l2x, l2y) <= r Then Return True
    
    //Vectors
    SegVecX# = l2x - l1x 
    SegVecY# = l2y - l1y
    
    PntVec1X# = cx - l1x
    PntVec1Y# = cy - l1y
    
    PntVec2X# = cx - l2x
    PntVec2Y# = cy - l2y
    
    //Dot products
    dp1# = SegVecX * PntVec1X + SegVecY * PntVec1Y
    dp2# = -SegVecX * PntVec2X - SegVecY * PntVec2Y
    
    //Check's whether one of the DPs is zero.
    //or signs are same
    If dp1 = 0 Or dp2 = 0 Then
    ElseIf Sign(dp1) = Sign(dp2) Then
    Else
        Return False
    EndIf
    
    //'Formula' of the line
    a# = (l2y - l1y) / (l2x - l1x)
    b# = -1
    c# = -(l2y - l1y) / (l2x - l1x) * l1x + l1y
    
    //Distance
    d# = Abs(a * cx + b * cy + c) / Sqrt(a * a + b * b)
    
    //Circle is too far
    If d > r Then Return False
    
    //If function reaches this point, circle and line segment DO intersect each other
    Return True
EndFunction
CoolBasic henkilökuntaa
Tech-kehittäjä
CoolBasic Classic, Cool VES

CoolPhysicsEngine | MissileSystem | Jana-ympyrä -törmäys | cbSimpleTexture | CoolCPLX
User avatar
CCE
Artist
Artist
Posts: 650
Joined: Mon Aug 27, 2007 9:53 pm

Re: Hankala kysymys...

Post by CCE »

Aika pro viritys, hyöty on suuri varsinkin piirtokomennoilla toteutetuissa peleissä.

Itse tulen tätä luultavasti käyttämään.
Edit: Tämän voisikin melkein laittaa ihan selkeyden nimissä tuonne esimerkkikoodit alueelle.
SPuntte
Tech Developer
Tech Developer
Posts: 650
Joined: Mon Aug 27, 2007 9:51 pm
Location: Helsinki, Finland
Contact:

Re: Hankala kysymys...

Post by SPuntte »

Lisäsin esimerkkikoodeihin. Samalla muutin kommentit suomeksi ja siistin koko hommaa vielä vähän lisää -> viewtopic.php?f=12&t=574
CoolBasic henkilökuntaa
Tech-kehittäjä
CoolBasic Classic, Cool VES

CoolPhysicsEngine | MissileSystem | Jana-ympyrä -törmäys | cbSimpleTexture | CoolCPLX
Post Reply