Mam taki problem. Są dane 3 puntky o określonych współrzędnych. Jak policzyć miarę kąta jaki tworzą?
Jak punkty mogą tworzyć kąt?
Trzy punkty ABC, kąt 'a' między wektorami BA = u i BC = v
Iloczyn skalarny:
uv = uxvx+uy*vy = |u||v|cos a;
Z tego wyliczasz ten c = cosa -> a = arccos c, otrzymamy kąt a<0,Pi>
Aby obliczyć kąt <0,2Pi> należy obliczyć jeszcze sin a (iloczyn wektorowy)
Można też z twierdzenia cosinusów i sinusów.
a jest jakaś funkcja do tego?(nie chodzi mi o sin i cos)
a z tymi punktami jest tak, że tworzą dwie linie, czyli ramiona kąta.
ale trzy punkty "mogą tworzyć" trzy kąty, a właściwie 6 - skąd program ma wiedzieć o który ci kąt chodzi ?
najprostszy sposób jaki mi przychodzi do głowy to
- obliczasz równania prostych, które pokrywają się z ramionami kąta
- obliczasz konty między poszczególnymi ramionami a półprostą ox
- obliczasz szukany kąt
Piszę, żeby rozwiać wątpliwości.
Są trzy punkty:
Razem tworzą taki kąt:
Wiem, że z trzech punktów może powstać 6 kątów, ale mi chodzi o ten jeden, program też wie, o który kąt chodzi.
Witam.
Również miałem ten problem i mając wsp 3 punktów, chciałem policzyć kąt miedzy nimi.
Jako, że studiuję geodezję, oczywistym dla mnie było iże policzę najpierw Azymuty (Punkt: Centralny-Prawy, oraz Centralny-Lewy) i je od siebie odejmę. Wartość otrzymana będzie kontem.
Czym jest Azymut i jak sie go liczy - to akurat nie jest wyzwanie i wierze, że każdy sobie z tym poradzi:)
Przy wpisywaniu współrzędnych mam wyszczególnione, który punkt jest Lewy, który Centralny, a który Prawy.
W procedurze jest sporo warunków, gdyż...hym... czasem po obliczeniu wartości Azymutu trzeba dodać, lub odjąć Pi, lub PI/2.
Co prawda pracedura jest tylko dla gradów, ale za czas jakiś będe robił dla stopni (a to akurat wyzwaniem nie jest). Wrzucę gdy zrobię przeliczanie z rad na Stopnie, minuty, sekundy...
pozdrawiam
P.S. aha, gwoli wyjaśnienia zapis np XP-wspX punktu prawego.
procedure TForm1.LiczClick(Sender: TObject);
var
XL,YL,XP,YP,XC,YC,AZ1,AZ2,DelXPC,DelYPC,DelYLC,DelXLC,K: real;
begin
try
XL:= StrToFloat (WspLX.Text); except on EConvertError do ShowMEssage ('X punktu L powinna byc liczba');
end; try
YL:= StrToFloat (WspLY.Text); except on EConvertError do ShowMEssage ('Y punktu L powinna byc liczba');
end; try
XP:= StrToFloat (WspPX.Text); except on EConvertError do ShowMEssage ('X punktu P powinna byc liczba');
end; try
YP:= StrToFloat (WspPY.Text); except on EConvertError do ShowMEssage ('Y punktu P powinna byc liczba');
end; try
XC:= StrToFloat (WspCX.Text); except on EConvertError do ShowMEssage ('X punktu C powinna byc liczba');
end; try
YC:= StrToFloat (WspCY.Text); except on EConvertError do ShowMEssage ('Y punktu C powinna byc liczba');
end;
DelYLC:= (YL-YC);
DelXLC:= (XL-XC);
DelYPC:= (YP-YC);
DelXPC:= (XP-XC);
begin
if((YL-YC)>0) And ((XL-XC)>0) then
AZ1:= ArcTan((DelYLC)/(DelXLC));
if((YL-YC)>0) And ((XL-XC)<0) then
AZ1:= PI + (ArcTan((DelYLC)/(DelXLC)));
if((YL-YC)<0) And ((XL-XC)>0) then
AZ1:= (ArcTan((DelYLC)/(DelXLC))) + (2*PI);
if((YL-YC)<0) And ((XL-XC)<0) then
AZ1:= PI + (ArcTan((DelYLC)/(DelXLC)));
if((YL-YC)=0) And ((XL-XC)>0) then
AZ1:= 0;
if((YL-YC)=0) And ((XL-XC)<0) then
AZ1:= PI;
if((YL-YC)>0) And ((XL-XC)=0) then
AZ1:= PI/2;
if((YL-YC)<0) And ((XL-XC)=0) then
AZ1:= (3/4)*PI;
if(YL=YC) And (XL=XC) then
begin
AZ1:=0;
ShowMessage ('Sprawdz poprawnosc wprowadzonych danych przy obliczaniu AZ1');
end;
Azymut1.Caption:=FloatToStrF(RadToGrad(AZ1),ffFixed,7,4);
end;
begin
if((YP-YC)>0) And ((XP-XC)>0) then
AZ2:= ArcTan((DelYPC)/(DelXPC));
if((YP-YC)>0) And ((XP-XC)<0) then
AZ2:= PI + (ArcTan((DelYPC)/(DelXPC)));
if((YP-YC)<0) And ((XP-XC)>0) then
AZ2:= (ArcTan((DelYPC)/(DelXPC))) + (2*PI);
if((YP-YC)<0) And ((XP-XC)<0) then
AZ2:= PI + (ArcTan((DelYPC)/(DelXPC)));
if((YP-YC)=0) And ((XP-XC)>0) then
AZ2:= 0;
if((YP-YC)=0) And ((XP-XC)<0) then
AZ2:= PI;
if((YP-YC)>0) And ((XP-XC)=0) then
AZ2:= PI/2;
if((YP-YC)<0) And ((XP-XC)=0) then
AZ2:= (3/4)*PI;
if(YP=YC) And (XP=XC) then
begin
AZ2:=0;
ShowMessage ('Sprawdz poprawnosc wprowadzonych danych przy bliczaniu AZ2');
end;
Azymut2.Caption:=FloatToStrF(RadToGrad(AZ2),ffFixed,7,4); //zamiana rad na grady
end; // oraz zaokrąglanie wyniku
// do 4 miejsc po przecinku
begin
if Az2>Az1 then
K:= Az2-Az1;
if Az2<Az1 then
K:= (2*PI-Az1)+Az2;
if Az1=Az2 then
begin
ShowMessage ('Sprawdz poprawnosc wprowadzonych danych');
K:=0;
end;
Kat.Caption:=FloatToStrF(RadToGrad(K),ffFixed,7,4);
end;
end;
</delphi>
var Punkty: array [0..2] of TPoint; //Wierzchołkiem kąta będzie Punkty[1]
Kat:double;
const PI2=PI*2;
begin
//Ustalenie punktow
Punkty[0]:=Point(10, 10);
Punkty[1]:=Point(0, 10);
Punkty[2]:=Point(0, 20);
//Obliczenie kata [rad]
Kat:=ArcTan2(Punkty[0].Y-Punkty[1].Y, Punkty[0].X-Punkty[1].X)-
ArcTan2(Punkty[2].Y-Punkty[1].Y, Punkty[2].X-Punkty[1].X);
//Sprowadzenie do zakresu [0..2PI]
while (Kat<0) do
Kat:=Kat+PI2;
while (Kat>PI2) do
Kat:=Kat-PI2;
//Pokazanie
Caption:=FloatToStr(RadToDeg(Kat));
end;
Funkcja ArcTan2, od ArcTan różni się tym, że zwraca kąt we właściwej ćwiartce.
Swoją drogą, w jakim celu wygrzebujesz tak starego posta? Nekrofilia czy jak ;)