Avatar billede alexander_j Nybegynder
02. januar 2005 - 19:05 Der er 16 kommentarer og
2 løsninger

geometri hehe

Hvis jeg har et liniestykke der er defineret med x1,y1 -> x2,y2
Og jeg har en cirkel med centrum i punktet x0,y0 og med radius 10

Hvordan kan jeg så tjekke om cirklen og liniestykket har fælles punkter (eller på nudansk: rører hinanden)?
Avatar billede barklund Nybegynder
02. januar 2005 - 20:02 #1
Det handler bare om at teste, at korteste afstand fra linjen til centrum af cirklen er mindre end cirklens radius. Og afstand mellem linje og punkt er ganske veldefineret og let at finde information om.

Jeg kigger lige på noget ;)
Avatar billede alexander_j Nybegynder
02. januar 2005 - 20:52 #2
Pyha det blev en være omgang - måske den kan forkortes?

if( ((x0>x1 and x0<x2) or (x0>x2 and x0<x1)) and ((y0>y1 and y0<y2) or (y0>y2 and y0<y1)) ){
    distance = ( x0*( y2-y1 )/( x2-x1 ) + y1 - x1*( y2-y1 )/( x2-x1 ) - y0 ) / Math.sqrt( (( y2-y1 )/( x2-x1)) * (( y2-y1 )/( x2-x1)) + 1 );
    if(distance<0) distance = -1*distance;
    if(distance<r0) trace("fælles punkter");
}
Avatar billede pyroman Nybegynder
02. januar 2005 - 21:06 #3
Skal jeg ikke også komme med et bud? ;)

Nu har jeg leget lidt matematik og kommet frem til følgende funktion: (hang on):


function Line (x1, y1, x2, y2){
    this.x1 = x1;
    this.x2 = x2;
    this.y1 = y1;
    this.y2 = y2;
}
function Circle (x, y, r){
    this.x = x;
    this.y = y;
    this.r = r;
}
function circleLineIntersect (lineObj, circleObj){
   
    // Linie beskrivelse
    a = (lineObj.y2-lineObj.y1)/(lineObj.x2-lineObj.x1);
    b = lineObj.y1-a*lineObj.x1
   
    // Cirkel beskrivelse
    cx = circleObj.x;
    cy = circleObj.y;
    r = circleObj.r;
   
    // De store udregninger
    x1 = (Math.sqrt((a*a)*((r*r)-(cx*cx))+2*a*cx*(cy-b)-(b*b)+2*b*cy-(cy*cy)+(r*r))+a*(cy-b)+cx) / ((a*a)+1);
    x2 = -(Math.sqrt((a*a)*((r*r)-(cx*cx))+2*a*cx*(cy-b)-(b*b)+2*b*cy-(cy*cy)+(r*r))+a*(b-cy)-cx) / ((a*a)+1);
   
    y1 = a*x1+b;
    y2 = a*x2+b;
   
    if(!isNaN(x1) && !isNaN(x2)){
        return {x1: x1, y1: y1, x2: x2, y2: y2};
    }else if(!isNaN(x1) && isNaN(x2)){
        return {x1: x1, y1: y1};
    }else if(isNaN(x1) && !isNaN(x2)){
        return {x1: x2, y1: y2};
    }else{
        return false;
    }
}

l1 = new Line(0,-10,4,-9); // linien er udenfor cirklen
l2 = new Line(0,-1,2,-3); // linien skærer cirklen
c1 = new Circle(2,2,10); // cirklen

trace(circleLineIntersect(l1,c1));
trace(circleLineIntersect(l2,c1));



Den kan det hele!
Hvis linien skærer cirklen, så returnere den et objekt med skæringspunkterne - eller returnerer den false!!
Avatar billede alexander_j Nybegynder
02. januar 2005 - 22:04 #4
Det ser godt ud - jeg gemmer dit script til senere brug - mit eget, lavet efter dit forslag, virker fint til formålet:
http://www.vestermarie-skole.dk/temp/lines_the_game.html

Kom med et svar :-D
Avatar billede pyroman Nybegynder
02. januar 2005 - 22:22 #5
Ahh - fikst spil! Jeg fik 750 point!! :)

Skæringspunkter har du ikke brug for nej - men jeg blev sgu lige opsat på at lave noget der kunne... og kan højst sandsynligt også selv bruge det på et tidspunkt!
Avatar billede barklund Nybegynder
02. januar 2005 - 23:36 #6
Jeg kan overhovedet ikke overskue jeres sindsygt lange formler - men det er vel nok rigtige. Jeg tror jeg laver en eller anden pædagogisk gennemgang i stedet ;)
Avatar billede barklund Nybegynder
02. januar 2005 - 23:55 #7
Og pyroman, husk at var'e alle de lokale variabler, som du bruger i dine funktioner. Hvad nu hvis man havde et script med:

a = 2;
...
circleLineIntersect(line, circle);
....
trace(a);  // funktionen har ændret a - sådan en bølle!

Det er generelt godt at huske, altid at var'e alle variabler, selvom det for tidslinjevariabler i praksis er lige meget.
Avatar billede alexander_j Nybegynder
02. januar 2005 - 23:56 #8
Liniens ligning:
y = a*x + b

Afstandsformel mellem punktet P0(x0,y0) og linien l:
dist(P,l) = (a*x0 + b - y0)/Math.sqrt(a*a + 1)

Har du to punkter på linien P1(x1,y1) og P2(x2,y2), så kan du finde hældningskooficenten:
a = (y2-y1) / (x2-x1)
og du kan også finde liniensskæringspunkt i y-aksen (b):
b = y1 / a*x1


Så tilbage til afstandsformlen - her er det bare at indsætte de forskellige variabler - eller måske mere overskueligt lave koden i flere etaper:
//cirklens centrum P0(x0,y0) og radius r
//første punkt på linien P1(x1,y1)
//andet punkt på linien P2(x2,y2)
a = (y2-y1) / (x2-x1);
b = y1 / a*x1;
afstand = (a*x0 + b - y0)/Math.sqrt(a*a + 1);
//da en afstand ikke kan være negativ må den gøres positiv, hvis den er negativ
if(afstand<0) afstand = -1*afstand;
if(afstand<r) trace("linien ramme cirklen");

Det var den pædagogiske gennemgang af min del af koden :-D
Avatar billede alexander_j Nybegynder
03. januar 2005 - 00:05 #9
Ups lille hygge fejl med beregningen af b - her er den rigtige kode:
a = (y2-y1) / (x2-x1);
b = y1 - a*x1;
afstand = Math.round( (a*x0 + b - y0)/Math.sqrt(a*a + 1) );
if(afstand<0) afstand = -1*afstand;
if(afstand<r) trace("linien ramme cirklen");
Avatar billede barklund Nybegynder
03. januar 2005 - 00:25 #10
Det var nu ikke så meget, hvordan man beregner det, for det er jeg med på, men det er nu mere, at ovenstående script ikke vil være mange millisekunder længere tid om at køre end dit oprindelige - mens vedligeholdelse af det overskuelige script kan være mange timer nemmere :)
Avatar billede barklund Nybegynder
03. januar 2005 - 03:23 #11
Så har jeg bikset med det længe nok:

http://actionscript.dk/artikler/?t=Punkt_til_linje

Selvom der stadig er en del uforklarede ting omkring simpel geometri - det må vente til en anden artikel en anden dag.

--
Morten Barklund
Avatar billede barklund Nybegynder
03. januar 2005 - 03:24 #12
(damn det er sent - igen i dag... nu vil jeg sove :/)
Avatar billede pyroman Nybegynder
03. januar 2005 - 16:46 #13
hæhæ - ja jeg må har glemt at smide de små detaljer på variablerne - plerjer jeg sgu ellers ikke at glemme.
Kan godt forstå koden er uoverskuelig - men det simpelthen "the way to do it" - smækkede formlen for en linie og en cirkel ind i programmet derive og fik den til at isolere x, det er ikke helt simpelt, derfor er der heller ikke nogen simpel løsning ;)

Men kan da godt supplere din artikel med lidt om geometrien hvis det skal være :)
Avatar billede alexander_j Nybegynder
03. januar 2005 - 16:56 #14
Nå skal vi ha fordelt lidt point her eller hva´?
Avatar billede barklund Nybegynder
03. januar 2005 - 17:19 #15
Aij, snød du og fik et program til at udlede det? Fusker :)

Anyways, et lille bitte svar, selvom jeg jo egentlig ikke kom med svaret først :)
Avatar billede alexander_j Nybegynder
03. januar 2005 - 17:50 #16
du ledte mig da på sporet ved at sige at jeg skulle finde den korteste vej til linien og sammenligne den med radius i cirklen (det var faktisk der jeg sad fast) - men pyroman kan da få del i det enorme point gilde for sine gode indsats :-D
Avatar billede pyroman Nybegynder
03. januar 2005 - 18:10 #17
hehe - hvis vi alle skal starte forfra med alting og ikke bruge hjælpemidler ville vi bremse vores egen udvikling og i stedet for at blive vist på en computerskærm ville eksperten.dk være hugget ind i en stentavle!
Tag nu de fleste af pointene selv - du fandt selv ud af det - mit script var bare et lille show off ;)
Avatar billede pyroman Nybegynder
03. januar 2005 - 18:10 #18
for det er jo enorme mængder point du fyrer af dér! - så de skulle ikke havne hos de forkerte! ;)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester