2012-09-02 29 views
16

Bu yüzden, A karakterinin belirli bir B mesafesi içinde olması durumunda A karakterinin B karakterini görebileceği başka bir karakterin "görebileceği" olup olmadığını kontrol ettiğim küçük bir oyun yapıyorum. A derecelerinde B, B açısına bakıldığında +/- 45 derecedir.Bir açı iki açı arasında olup olmadığının hesaplanması

Şu anda, bu biz 360 derece çizgisini geçerken dışında çalışıyor

(facingAngle - 45) =< angleOfTarget =< (facingAngle + 45) 

eğer kontrol ediyorum biraz hesaplama yapmak.

facingAngle = 359, angleOfTarget = 5 diyelim. Bu durumda, hedef merkezde sadece 6 derece, bu yüzden işlevimin geri dönmesini istiyorum. Ne yazık ki, 5 değil 314 ila 404.

+0

Olası kopyalar (http://stackoverflow.com/questions/11406189/determine-if-angle-lies- -2-diğer açılarda) – sschuberth

cevap

14

Sadece nedeni farkı olduğunu

anglediff = (facingAngle - angleOfTarget + 180 + 360) % 360 - 180 

if (anglediff <= 45 && anglediff>=-45) .... 

deneyin:

, sen angleOfTarget değere başka ekleyerek tekrar kontrol etmeniz gerekir en sonunda sarma işlemek için açılarda facingAngle - angleOfTarget olmasına rağmen, sarma efektleri nedeniyle, 360 derece kapalı olabilir.

180 + 360 sonra modulo 360'ı ekleyin ve ardından 180'i çıkarın, etkin bir şekilde her şeyi -180 ila 180 derece (sadece 360 ​​derece ekleyerek veya çıkartarak) dönüştürür.

Ardından açı farkını -45 ila 45 derece arasında olup olmadığını kolayca kontrol edebilirsiniz.

+1

Köknarlarda t Konuyla ilgili davada çalışmıyordum, ama sonra Python'da test ettim .. Çalışıyorum! Bu yüzden neden orada çalışmadığını anlayabilmek için Pascal'a geri döndüm, Pascal'daki 'mod'un negatif sayılarla çalışmadığı ortaya çıkıyor ... – JHolta

+1

Bu, faceAngle'ın 0 ve angleOfTarget'in 359 olduğu durumlarda başarısız oluyor. Örneğin. Bir şey özlemediğim sürece, (0 - 359 + 180)% 360 - 180 = -359 elde edersiniz. BakanAngle - angleOfTarget çıkarma işleminin çevresinde mutlak bir değer gereklidir. –

+0

Java'da tamamen test edildi (Android). İşe yarıyor. – pascalbros

0

(negatif değerlere) düşük sonunda sarma işlemek için basit bir çözümdür, tüm değerlerine 360 ​​eklemek için sadece geçerli:

(facingAngle + 315) =< (angleOfTarget + 360) =< (facingAngle + 405) 

Bu şekilde, 45'in çıkarılması asla negatif olmaz, çünkü artık olmaz.

canSee = (facingAngle + 315 <= angleOfTarget + 360) && 
      (angleOfTarget + 360 <= facingAngle + 405); 
canSee |= (facingAngle + 315 <= angleOfTarget + 720) && 
      (angleOfTarget + 720 <= facingAngle + 405); 
8

Sarma sorununu önleyen trigonometrik bir çözüm var.

Her iki karakter için de (x, y) koordinatlarınızın P1 ve P2 olduğunu varsayalım. Pythagoras teoremi kullanılarak hesapladığınız iki arasındaki mesafeyi bildiğinizi zaten belirttiniz. Eğer [cos(fA), sin(fA)] olacak facingAngle vektörü olarak A alırsak

A . B = |A| . |B| . cos(theta). 

ve adımları attıklarını 1 |A| sahip olacaktır:

Sen aralarındaki açı hesaplamak için nokta ürünü iki vektörleri kullanabilirsiniz.

iki karakter arasında vektörü olarak B almak ve sizin yukarıdaki mesafe alırsanız:

cos(theta) = (cos(fA) * (P2x - P1x) + sin(fA) * (P2y - P1y))/|B| 

Burada zaten hesaplanmış olduğunuz mesafe |B| olduğunu.

Sen aslında sadece cos(theta) >= 0.70710678 (yani 1/sqrt(2)) için kontrol edilmesi gereken -45 45 ila aralığı için çünkü theta bulmak için ters kosinüsünü almak gerekmez.

Bu, biraz karmaşık görünebilir, ancak olasılık zaten zaten programınızda asılı olan tüm gerekli değişkenleri zaten aldık.

6

İşte çevrimiçi bulduğum ve değiştirdiğim basit bir işlev. Herhangi bir açı için düzgün çalışır (0-360'ın dışında olabilir). (Bu işlev Xcode çalışır c çalışmak için yapılır.)

Unutmayın, açı B'ye açı A saatin tersi yönünde denetler O döndüren açı ise EVET (doğru) :)

arasında açı :)

//check if angle is between angles 
static inline BOOL angle_is_between_angles(float N,float a,float b) { 
N = angle_1to360(N); //normalize angles to be 1-360 degrees 
a = angle_1to360(a); 
b = angle_1to360(b); 

if (a < b) 
return a <= N && N <= b; 
return a <= N || N <= b; 
} 

arasında ise

İlk olarak, basit dönüşüm fonksiyonu tüm açılar 1-360

//function to convert angle to 1-360 degrees 
static inline double angle_1to360(double angle){ 
angle=((int)angle % 360) + (angle-trunc(angle)); //converts angle to range -360 + 360 
if(angle>0.0) 
return angle; 
else 
return angle + 360.0; 
} 

kontrol yapmak

Ör. Açı 300 180 ila 10 derece olup olmadığını kontrol etmek için:

BOOL isBetween=angle_is_between_angles(300, 180,10); 

// EVET İade

+1

trunc() Math.floor() ile değiştirilirse Java için çalışır. – mindoverflow

0

daima asgari pozitif fark kullanılarak ve eşik ile karşılaştıran bir başka yolu: Alnitak yanıtını Tekrarlamamız

anglediff = Math.min(Math.abs(facingAngle - angleOfTarget), 360 - Math.abs(angleOfTarget - allowDirection)); 
if (anglediff <= 45) 
0

farklı bir şekilde, açı sargısını 360 dereceden kaçınan bir çözüm, açıları her zaman küçük olan farklı bir koordinat sisteminde sorunu yeniden ifade etmektir.

def inside_angle(facing, target): 
    dot = cos(facing)*cos(target) + sin(facing)*sin(target) 
    angle = acos(dot) 

    return angle <= pi/4 

Bu vektör projeksiyonu kullanılarak yapılır: Burada kodudur. Vektörleri varsayarsak> = [cos (bakan) günah (yüz)] ve | target> = [cos (hedef) günah (hedef)], hedeflenen vektöre hedefin projeksiyonu yapılırken, açı sıfırdan Hedef tam olarak yüz vektörüdür veya her iki tarafa da artar. Bu şekilde sadece pi/4 (45 derece) ile karşılaştırabiliriz. açı için formül şudur: | bakacak> ve |

olduğunu
cos(angle) = <facing|target>/<target|target> <facing|facing> 

, açının kosinüs vektörler arasındaki nokta ürünüdür hedef> bu durumda 1 olan kendi modülleri, bölünmüş hangi gibi olur:

angle = acos(<facing|target>) 

Referans: https://en.wikipedia.org/wiki/Vector_projection

[açısı 2 diğer açıları arasında kaldığı takdirde belirlemek] arasında