2011-10-16 24 views
19

है, मैं एक समस्या पर काम कर रहा हूं जो प्रोफेसर असाइन किया गया है, और मुझे यह पता लगाने में कोई समस्या है कि 3 अंक के बीच कोण 180 डिग्री से अधिक है, उदाहरण के लिए:यह पता लगाना कि कोण 180 डिग्री से अधिक

मैं अगर अल्फा से अधिक 180 डिग्री है पता लगाने के लिए चाहते हैं। वैसे भी, मेरे प्रोफेसर के पास एक कोड है जो समस्या हल करता है, लेकिन उसके पास ज़क्रॉस नामक एक फ़ंक्शन है, लेकिन मुझे बिल्कुल नहीं पता कि यह कैसे काम करता है। क्या कोई मुझे बता सकता है? उनकी कोड यहाँ है:

#include <fstream.h> 
#include <math.h> 
#include <stdlib.h> 

struct point { 
    double x; 
    double y; 
    double angle; 
}; 

struct vector { 
    double i; 
    double j; 
}; 

point P[10000]; 
int  hull[10000]; 

int 
zcross (vector * u, vector * v) 
{ 
    double p = u->i * v->j - v->i * u->j; 
    if (p > 0) 
    return 1; 
    if (p < 0) 
    return -1; 
    return 0; 
} 

int 
cmpP (const void *a, const void *b) 
{ 
    if (((point *) a)->angle < ((point *) b)->angle) 
    return -1; 
    if (((point *) a)->angle > ((point *) b)->angle) 
    return 1; 
    return 0; 
} 

void 
main() 
{ 
    int  N, i, hullstart, hullend, a, b; 
    double midx, midy, length; 
    vector v1, v2; 

    ifstream fin ("fc.in"); 
    fin >> N; 
    midx = 0, midy = 0; 
    for (i = 0; i < N; i++) { 
     fin >> P[i].x >> P[i].y; 
     midx += P[i].x; 
     midy += P[i].y; 
    } 
    fin.close(); 
    midx = (double) midx/N; 
    midy = (double) midy/N; 
    for (i = 0; i < N; i++) 
     P[i].angle = atan2 (P[i].y - midy, P[i].x - midx); 
    qsort (P, N, sizeof (P[0]), cmpP); 

    hull[0] = 0; 
    hull[1] = 1; 
    hullend = 2; 
    for (i = 2; i < N - 1; i++) { 
     while (hullend > 1) { 
      v1.i = P[hull[hullend - 2]].x - P[hull[hullend - 1]].x; 
      v1.j = P[hull[hullend - 2]].y - P[hull[hullend - 1]].y; 
      v2.i = P[i].x - P[hull[hullend - 1]].x; 
      v2.j = P[i].y - P[hull[hullend - 1]].y; 
      if (zcross (&v1, &v2) < 0) 
       break; 
      hullend--; 
     } 
     hull[hullend] = i; 
     hullend++; 
    } 

    while (hullend > 1) { 
     v1.i = P[hull[hullend - 2]].x - P[hull[hullend - 1]].x; 
     v1.j = P[hull[hullend - 2]].y - P[hull[hullend - 1]].y; 
     v2.i = P[i].x - P[hull[hullend - 1]].x; 
     v2.j = P[i].y - P[hull[hullend - 1]].y; 
     if (zcross (&v1, &v2) < 0) 
      break; 
     hullend--; 
    } 
    hull[hullend] = i; 

    hullstart = 0; 
    while (true) { 
     v1.i = P[hull[hullend - 1]].x - P[hull[hullend]].x; 
     v1.j = P[hull[hullend - 1]].y - P[hull[hullend]].y; 
     v2.i = P[hull[hullstart]].x - P[hull[hullend]].x; 
     v2.j = P[hull[hullstart]].y - P[hull[hullend]].y; 
     if (hullend - hullstart > 1 && zcross (&v1, &v2) >= 0) { 
      hullend--; 
      continue; 
     } 
     v1.i = P[hull[hullend]].x - P[hull[hullstart]].x; 
     v1.j = P[hull[hullend]].y - P[hull[hullstart]].y; 
     v2.i = P[hull[hullstart + 1]].x - P[hull[hullstart]].x; 
     v2.j = P[hull[hullstart + 1]].y - P[hull[hullstart]].y; 
     if (hullend - hullstart > 1 && zcross (&v1, &v2) >= 0) { 
      hullstart++; 
      continue; 
     } 
     break; 
    } 

    length = 0; 
    for (i = hullstart; i <= hullend; i++) { 
     a = hull[i]; 
     if (i == hullend) 
      b = hull[hullstart]; 
     else 
      b = hull[i + 1]; 
     length += sqrt ((P[a].x - P[b].x) * (P[a].x - P[b].x) + (P[a].y - P[b].y) * (P[a].y - P[b].y)); 
    } 

    ofstream fout ("fc.out"); 
    fout.setf (ios: :fixed); 
    fout.precision (2); 
    fout << length << '\n'; 
    fout.close(); 
} 

उत्तर

36

सबसे पहले, हम जानते हैं कि sin(a) ऋणात्मक है, तो कोण 180 डिग्री से अधिक है।

हम sin(a) का संकेत कैसे प्राप्त करते हैं? यहां वह जगह है जहां क्रॉस उत्पाद खेलने में आता है।

सबसे पहले, के दो वैक्टर परिभाषित करते हैं:

v1 = p1-p2 
v2 = p3-p2 

इसका मतलब है कि दो वैक्टर p1 को p2 और एक अंक और p3 करने के लिए अन्य बिंदुओं पर शुरू करते हैं।

क्रॉस उत्पाद के रूप में परिभाषित किया गया है:

(x1, y1, z1) x (x2, y2, z2) = (y1z2-y2z1, z1x2-z2x1, x1y2-x2y1) 

के बाद से अपने वैक्टर 2 डी में कर रहे हैं, तो z1 और z2 0 और इसलिए कर रहे हैं:

(x1, y1, 0) x (x2, y2, 0) = (0, 0, x1y2-x2y1) 

है यही कारण है कि वे इसे zcross क्योंकि फोन उत्पाद के केवल z तत्व के पास 0

के अलावा अन्य मान है, दूसरी ओर, डब्ल्यू ई जानते हैं कि:

||v1 x v2|| = ||v1|| * ||v2|| * abs(sin(a)) 

जहां ||v|| वेक्टर v का आदर्श (आकार) है। साथ ही, हम जानते हैं कि अगर कोण a 180 से कम है, तो v1 x v2 ऊपर की ओर इंगित करेगा (दाएं हाथ का नियम), जबकि 180 से बड़ा यह इंगित करेगा। तो अपने विशेष मामले में:

(v1 x v2).z = ||v1|| * ||v2|| * sin(a) 

सीधे शब्दों में कहें, अगर v1 x v2 की जेड मूल्य सकारात्मक है, तो a 180 से छोटी है अगर यह नकारात्मक है, तो यह बड़ा है (जेड मूल्य x1y2-x2y1 था)। यदि क्रॉस उत्पाद 0 है, तो दो वैक्टर समानांतर होते हैं और कोण या तो 0 या 180 होता है, इस पर निर्भर करता है कि दोनों वैक्टर क्रमशः समान या विपरीत दिशा में हैं या नहीं।

+0

धन्यवाद ध्यान देंगे। अच्छा और सूचनात्मक उत्तर। –

+2

2 डी में, आप वास्तव में क्या कर रहे हैं "बाहरी उत्पाद" की गणना कर रहा है, जो क्रॉस उत्पाद की तुलना में अधिक सामान्य अवधारणा है और किसी भी आयाम में काम करता है। वे इसे प्रारंभिक रैखिक बीजगणित कक्षाओं में नहीं पढ़ते हैं, जो शर्म की बात है। (फॉर्मूला ज्यादातर वही है, बस "z" निर्देशांक का कोई उल्लेख नहीं है, इसलिए यह आसान है।) –

+0

अच्छा जवाब। यह ठीक वही है जिसकी मुझे तलाश थी। –

3

zcross vector cross product (प्लस या जेड दिशा में ऋण) के हस्ताक्षर का उपयोग कर रहा है, तो कोण से अधिक या कम 180 डिग्री है निर्धारित करने के लिए, के रूप में आप इसे रख दिया है।

+0

हम्म, मैं में है कि अब –

0

यह इस प्रकार किया जाएगा करने के लिए एक और तरीका है:

calculate वेक्टर v1 = p2-p1, वी 2 = p2 -p3। फिर, क्रॉस-उत्पाद फ़ॉर्मूला का उपयोग करें: यू।वी = || यू || || v || कॉस (थेटा)

+0

आप कोणों को कैसे नियंत्रित करते हैं> 180 डिग्री? – Vertexwahn

+0

संकेत आपको बताता है कि यह 180 डिग्री से अधिक है, है ना? –

1

3 डी में, वैक्टर के क्रॉस उत्पाद को ढूंढें, क्रॉस उत्पाद की न्यूनतम लंबाई पाएं जो मूल रूप से केवल x, y और z की छोटी संख्या को ढूंढती है।

यदि सबसे छोटा मान 0 से छोटा है, तो वैक्टर का कोण नकारात्मक है।

कोड में

तो:

float Vector3::Angle(const Vector3 &v) const 
{ 
    float a = SquareLength(); 
    float b = v.SquareLength(); 
    if (a > 0.0f && b > 0.0f) 
    { 
     float sign = (CrossProduct(v)).MinLength(); 
     if (sign < 0.0f) 
      return -acos(DotProduct(v)/sqrtf(a * b)); 
     else 
      return acos(DotProduct(v)/sqrtf(a * b)); 
    } 
    return 0.0f; 
} 
+0

मुझे लगता है कि यह उल्लेख करना महत्वपूर्ण है कि फ़ंक्शन [-180 डिग्री; 180 डिग्री] के बीच एक कोण देता है - [0; 360 डिग्री] के बीच कोण नहीं - सही काम करता है! – Vertexwahn

संबंधित मुद्दे