Avatar billede bramsing Nybegynder
18. januar 2009 - 16:17 Der er 27 kommentarer og
1 løsning

Beregn den tætteste kurs mod vindens retning (mellem 0 og 359)

Jeg søger efter et spark videre til at kunne beregne hvilken kurs der ligger tættest på vinden kommer fra..

Eks.
Jeg har 2 kurser på hhv. 110 og 290 og vinden kommer fra 350..
Hvordan får jeg beregnet frem at det er 110 der ligger tættest på ??

Jeg har søgt lidt på Sin, Cos, DegToRad/RadToDeg m.v. men jeg er ikke sikker på om jeg er på rette vej...

Er der en der kan/vil give mig et spark videre (hjælpe) ??
(Har tidligere oprettet dette spørgsmål om det samme, http://www.eksperten.dk/spm/860215?message=&t=1232288602)
Avatar billede thesurfer Nybegynder
18. januar 2009 - 16:51 #1
Hmm.. umiddelbart ville jeg sige at 290 ligger tættest på 350:

350 - 290: 60 graders forskel

110 - 350 + 360: 120 graders forskel

Hvis antallet af grader bliver negativt, lægger man 360 grader til, for at det bliver positivt.
Avatar billede bramsing Nybegynder
18. januar 2009 - 17:00 #2
AARRRHH... Du har ret... Der skulle havde stået 010 og ikke 110... Jeg prøver lige at arbejde lidt videre med dit forslag...
Avatar billede thesurfer Nybegynder
18. januar 2009 - 17:03 #3
Hvis det er korrekt, så er formlen:

kurs 1:
k1a = 350 - 110
k1b = 110 - 350
hvis k1a < k1b
  kurs1 = k1a
ellers
  hvis k1b < 0
    kurs1 = k1b + 360
  ellers
    kurs1 = kb1
slut hvis

Det samme gøres med kurs 2 (erstat alle fremkomster af "k1" med "k2", "kurs1" med "kurs2")

Derefter skal de sammenlignes:
hvis kurs1 > kurs2
  kortest = kurs2
ellers
  kortest = kurs1
slut hvis

Det skal lige oversættes til Delphi..

.. vil jeg tro.. :-)
Avatar billede thesurfer Nybegynder
18. januar 2009 - 17:04 #4
010 er jo bare 10.. :-)

Så ovenstående burde stadig være korrekt..
Avatar billede a_nor Nybegynder
18. januar 2009 - 17:15 #5
Udfør Prik-produktet mellem de to vektorer.

procedure TForm1.Button1Click(Sender: TObject);
var v1,v2,v3,p2,p3:real;

begin
// vindretning i Edit1 = V1
v1 := StrTofloat(edit1.text);
v2 := StrTofloat(edit2.text);
v3 := StrTofloat(edit3.text);
P2 := COS(3.14592*V2/360)* COS(3.14592*V1/360) + SIN(3.14592*V2/360)*SIN(3.14592*V1/360);
P3 := COS(3.14592*V3/360)* COS(3.14592*V1/360) + SIN(3.14592*V3/360)*SIN(3.14592*V1/360);
Res2.caption := FloatToStr(p2);
Res3.caption := FloatToStr(p3);
end;

Herefter kan du ud af resultaterne (p2 og p3 afgøre hvilken vinkel der er tættest på v1
Avatar billede thesurfer Nybegynder
18. januar 2009 - 17:15 #6
Med ovenstående kode, og "010" som kurs 1, "290" som kurs 2, "350" som ønsket kurs, ser regnestykket sådan ud:

k1a = 350 - 10 (=340)
k1b = 10 - 350 (-340)
da k1a (340) ikke er mindre end k1b (-340)
da k1b (-340) er minde end 0, lægges 360 til, kurs1 = 20

..det samme gøres med "290"..


Til sidst:

hvis kurs1 (20) er mindre end kurs2 (60)
  korteste = kurs1 (20)
ellers
  korteste = kurs2 (60)
slut hvis

Da kurs1 (20) er mindre end kurs2 (60), er den korteste ved: kurs1
Avatar billede thesurfer Nybegynder
18. januar 2009 - 17:17 #7
a_nor> Jeg er klar over at der er en mere officel (sin/cos) tilgang, men den tilgang er mere processerkrævende end simpel matematik :-)
Avatar billede a_nor Nybegynder
18. januar 2009 - 17:30 #8
Men, øhhh, er din computer mere end 28 år gammel :-))

tjek  evt. http://en.wikipedia.org/wiki/Intel_8087
Avatar billede thesurfer Nybegynder
18. januar 2009 - 17:32 #9
a_nor>

Huh? Mere end 28 år gammel? Forstod jeg ikke lige.. og gad ikke at læse artiklen.. :-)


Anyways.. Din kode burde kunne optimeres sådan:

procedure TForm1.Button1Click(Sender: TObject);
var pi,v1,v2,v3,p2,p3:real;

begin
// vindretning i Edit1 = V1

pi360 := 3.14592 / 360;

v1 := StrTofloat(edit1.text);
v2 := StrTofloat(edit2.text);
v3 := StrTofloat(edit3.text);

V1 := v1/pi360;
V2 := v2/pi360;
V3 := v3/pi360;

P2 := COS(V2)* COS(V1) + SIN(V2)*SIN(V1);
P3 := COS(V3)* COS(V1) + SIN(V3)*SIN(V1);

Res2.caption := FloatToStr(p2);
Res3.caption := FloatToStr(p3);
end;

Jeg har ikke testet det, så jeg kan ikke sige om der er fejl i syntaxen osv..
Avatar billede thesurfer Nybegynder
18. januar 2009 - 17:34 #10
Der skulle have stået:

procedure TForm1.Button1Click(Sender: TObject);
var pi360,v1,v2,v3,p2,p3:real;

begin
// vindretning i Edit1 = V1

pi360 := 3.14592 / 360;

v1 := StrTofloat(edit1.text);
v2 := StrTofloat(edit2.text);
v3 := StrTofloat(edit3.text);

V1 := v1/pi360;
V2 := v2/pi360;
V3 := v3/pi360;

P2 := COS(V2)* COS(V1) + SIN(V2)*SIN(V1);
P3 := COS(V3)* COS(V1) + SIN(V3)*SIN(V1);

Res2.caption := FloatToStr(p2);
Res3.caption := FloatToStr(p3);
end;
Avatar billede thesurfer Nybegynder
18. januar 2009 - 17:35 #11
Vi prøver igen :-)

(der stod f.eks. "V1 := v1/pi360;" i stedet for "V1 := v1*pi360;")

procedure TForm1.Button1Click(Sender: TObject);
var pi360,v1,v2,v3,p2,p3:real;

begin
// vindretning i Edit1 = V1

pi360 := 3.14592 / 360;

v1 := StrTofloat(edit1.text);
v2 := StrTofloat(edit2.text);
v3 := StrTofloat(edit3.text);

V1 := v1*pi360;
V2 := v2*pi360;
V3 := v3*pi360;

P2 := COS(V2)* COS(V1) + SIN(V2)*SIN(V1);
P3 := COS(V3)* COS(V1) + SIN(V3)*SIN(V1);

Res2.caption := FloatToStr(p2);
Res3.caption := FloatToStr(p3);
end;
Avatar billede bramsing Nybegynder
18. januar 2009 - 20:24 #12
Hmm.. Det ser interessant ud.. og som det står kan jeg også få det til at virke... Som jeg lige har skrevet i det gamle spørgsmål, så er mit problem at det ikke altid er 2 kurser der ligger til grund.. men et sted mellem 2 og 10 der skal vurderes..

De ligger i en ini-fil på følg. måde

[omraade1]
HDN1=010
HDN2=190
HDN3=060
HDN4=240

[omraade2]
HDN1=110
HDN2=290
HDN3=040
HDN4=220
HDN5=120
HDN6=300

Når jeg i listbox vælger eksv. omraade1 så sker der en ReadSectionValues i ini-filen hvor den skriver HDN1, HDN2 .. .. .. .. ind i listbox2..
Samtidigt skal den ud fra en difineret vindretning finde den HDN i inifilen der ligger tættest på og skrive den i en Label..
Jeg håber ikke det er sortsnak...

Jeg kan ikke lige hitte ud af at få jeres eksempler drejet over i det mere dynamiske :-(
Avatar billede thesurfer Nybegynder
18. januar 2009 - 21:08 #13
bramsing> Kan du JavaScript? Da jeg ikke har Delphi, kan jeg lave et eksempel i JavaScript.. Det burde ikke være så svært at oversætte til Delphi..
Avatar billede bramsing Nybegynder
18. januar 2009 - 21:11 #14
Jeg er ikke en haj til det (og heller ikke til Delphi :-D men det går), men jo...
Avatar billede a_nor Nybegynder
19. januar 2009 - 09:47 #15
Du kan lave noget i retning af nedenstående. Din opgave er herefter at få indlæst områderetningerne i OmrText.  Se evt i Delphi-hjælpen om tStrings / tStringlist

var v1,v2,pi360,P2,Pmax : float;
    OmrText: array[1..20] of string;
    i, AntalElementer : integer; // i område.

v1  := StrTofloat(edit1.text);
V    := -1; // blot for at kunne se om der er fundet nogen
Pmax := -1;
Pi360 := 3.141592/360;
for i:= 1 to AntalElementer do
  begin
  v2 := StrTofloat(OmrText[i]);
  P2 := COS(Pi360*V2)* COS(Pi360*V1) + SIN(Pi360*V2)*SIN(Pi360*V1);
  if P2>Pmax then
    begin
    Pmax:= P2;
    V  := OmrText[i];
    end;
  end;
Din vindretning indlæses i edit1.
Dine områder indlæses i arrayet OmrText
V er herefter den retning der passer bedst ....
Avatar billede bramsing Nybegynder
19. januar 2009 - 19:42 #16
a_nor << Hvor og evt. hvordan definere jeg INIdata.Read{String/Section/SectionValues} ind i OmrText ??
Avatar billede a_nor Nybegynder
21. januar 2009 - 09:38 #17
Hej igen, var lige optaget igår ---

Der findes et unit der letter brugen af inifiles. Inkluder 'inifiles' i din uses.
herefter kan du f.eks skrive:  (Der skal selvfølgelig være en Button1 og en memo1 på formen)

procedure TForm1.Button1Click(Sender: TObject);
  var
  OmrText: tStringlist;
  IniFile : TIniFile;
  i:integer;
begin
  OmrText:= tStringlist.Create;
  IniFile := TIniFile.Create('c:\test.ini') ;
  inifile.ReadSection ('sektion1',OmrText);
  for i:= 0 to OmrText.Count-1 do
    memo1.lines.add(OmrText.strings[i]);
end;
Avatar billede bramsing Nybegynder
21. januar 2009 - 09:48 #18
Jeps... den del har fat i.. Men hvordan køres løkken så i forhold til beregningen af den kurs der ligger tættest på vinden ???
Avatar billede a_nor Nybegynder
22. januar 2009 - 12:38 #19
Prøv følgende, hvor resultatet vises i Label1

  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Memo1: TMemo;
    Edit1: TEdit;
    ComboBox1: TComboBox;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    IniFile : TIniFile;

  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
  var
  OmrText: tStringlist;
  //IniFile : TIniFile;
  i:integer;
  v,v1,v2,pi360,P2,Pmax : real;
  vs:string;

begin
OmrText:= tStringlist.Create;
inifile.ReadSectionValues (combobox1.Text,OmrText);
Pmax := -1;
try
  v1 := StrTofloat(edit1.text);
  except
    messagebox(0,'Fejl ved int.konvertering','',0);
  end;
Pi360 := 3.141592/360;
Memo1.Clear;
for i:= 0 to OmrText.Count-1 do
  begin
  memo1.lines.add(OmrText.strings[i]);

  v2 := StrTofloat(copy(OmrText.strings[i],pos('=',OmrText.strings[i])+1,30));
  P2 := COS(Pi360*V2)* COS(Pi360*V1) + SIN(Pi360*V2)*SIN(Pi360*V1);
  if P2>Pmax then
    begin
    Pmax:= P2;
    Vs  := OmrText.strings[i];
    end;
  label1.Caption := Vs;
  end;
omrText. Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
  // IniFile : TIniFile;
begin
IniFile := TIniFile.Create('c:\test1.ini') ;
inifile.ReadSections(combobox1.Items);
combobox1.ItemIndex:=0;
edit1.Text :='0';
end;
Avatar billede bramsing Nybegynder
22. januar 2009 - 21:43 #20
a nor.. Du har fat i noget der... Dog er der problemer omkring kurs 0 og 359...
Jeg har testet 2 kurser hhv. 030 og 290..
Når Vinden er kurs 359 viser den at det er kurs 290 (69 fra og hvor der er 31 til 030) der er tættest på.
Når Vinden er kurs 0 viser den at det er kurs 030 (30 fra) der er tættest på..

Jeg prøver at kigge lidt mere på den for at se om jeg kan få den til at makke ret :-D
Avatar billede bramsing Nybegynder
23. januar 2009 - 10:16 #21
a nor << Jeg tror jeg fik den til at virke...
Jeg skiftede "Pi360 := 3.141592/360;" ud med "Pi360 := (2*3.141592)/360;" og så virkede det... Lægger du et svar så kvittere jeg med Point og et MEGET STORT tak for hjælpen :-)
Avatar billede a_nor Nybegynder
23. januar 2009 - 11:15 #22
Godt du kunne bruge det. Og så beklager jeg selvfølgelig omsætningsfejlen mellem grader og Pi. Det var vist 8. eller 9. klasses stof :-(

Anders
23. januar 2009 - 17:28 #23
Jeg synes efterhånden at mange svar her på siden tangerer talemåden "At skyde gråspurve med kanoner".
Man burde måske gå i retning af KISS princippet "Keep It Simpel Stupid".

Lav følgende funktion, som beregner forskellen mellen to vinkler:

function TForm1.DeltaVinkel(B, W: Integer):Integer;
begin
  Result := Abs(B-W);
  if Result > 180 then // Hvis vinklen er over 180 grader, så er det den anden vej rundt;
    Result := 360 - Result;
end;

Så er det jo bare at køre en løkke som sammenligner alle vinkler, og udvælger den mindste.
Avatar billede arne_v Ekspert
23. januar 2009 - 18:02 #24
En helt tilsvarende loesning blev allerede givet for 5 dage siden i http://www.eksperten.dk/spm/860215 !
Avatar billede bramsing Nybegynder
23. januar 2009 - 21:38 #25
Anton og arne_v Jeg havde nu ikke det store problem i at finde den nærmeste kurs udfra 2 kurser... Mit problem lå i at der var et sted mellem 2 og 10 kurser i forskellige områder som jeg nærmere beskrev i kommentaren fra 18/01-2009 20:24:29...

Mit hoved problem lå i at trække kurserne ind i et array, stringlist e.lign. og der lave en samlet beregning og vælge den kurs der lå tætest på vindens retning...

Jeg kan ikke se at jeres løsning kom ind på det...

Kald mig bare stupid hvis du har overskud til det... Jeg har aldrig påstået at jeg var proff eller noget.. og hvis jeg var oprettede jeg sq nok heller ikke spørgsmål herinde... Da jeg har valgt a_nor's løsning tilfalder point til ham.. I andre er velkommen til at få point også.. Jeg opretter gerne et point spørgsmål til jer..

//Bramsing
24. januar 2009 - 13:51 #26
Undskyld at jeg spørger dumt.
Men, a_nor, hvor er guldkornene begravet med hensyn til sinus, cosinus og PI?

>Bramsig, det var nu ikke dig jeg hentydede til da jeg brugte udtrykket stupid, men alle dem her på siden der kommer med meget lange løsninger på simple problemer.

Mit forslag løser det problem der er formuleret i spørgsmålet, jeg kan godt se at spørgsmålet er vokset hen ad vejen. Jeg synes det er helt fint at a_nor fik dine point, da han leverede en brugbar løsning til dig.
Avatar billede a_nor Nybegynder
24. januar 2009 - 17:54 #27
>anton_kruse_andersen
Hvad mener du med guldkorn ?  I spørgsmålets formulering blev der spurgt om sin(), cos() kunne anvendes. Det kan de jo som du ser, og så kom den løsning mindre end ½ time efter spørgsmålet blev stillet mens din var flere dage undervejs :-). Så om det er at gå over åen, tjaa.
>Bramsig
Alle spørgsmål er velkomne. Det er jo kun den vej man får øget sin viden.
24. januar 2009 - 18:22 #28
Hej a_nor, jeg kan se at sin og cos kan bruges, men hvad er formålet?
Jeg kunne vel også spørge Monberg og Thorsen om jeg kunne låne/leje en af deres byggekraner til at bygge et legehus, og de ville sansynligvis svare ja.
Men derfor kan man da stadigvæk lige så godt bruge en simplere løsning. Det er det jeg mener med "Keep It Simpel".

Det her er ikke et forsøg på at stjæle dine point.
Og jeg giver dig ret i at alle spørgsmål er velkomne.

Mht. at mit svar var længe undervejs, min pc led under et mærkeligt "virus" angreb.
Jeg ville selvfølgelig teste mit svar før det blev afsendt, det lille program jeg skrev for at teste det, blev fanget af AVG og betegnet som et hack værktøj.
Efter utallige scan med flere forskellige antivirus, var det program jeg lige havde lavet det eneste de fandt som var virus befængt. og dette mærkelige problem skulle jeg da lige have styr på først.
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
Kurser inden for grundlæggende programmering

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