2012-03-02 21 views
9

से किसी दिए गए कोण पर सीधी रेखा से छेड़छाड़ किए गए यूआईवी व्यू आयत पर सीजीपॉइंट पाएं, मैं केंद्र बिंदु से परिधि रेखा से परिधि रेखा से छिद्रित आयत पर बिंदु निर्धारित करने की कोशिश कर रहा हूं पूर्व निर्धारित कोण पर आयताकार।आईओएस में केंद्र बिंदु

कहें कि मुझे केंद्र बिंदु, आयताकार का आकार, और कोण (पूर्व के लिए 0 डिग्री से शुरू होता है और उत्तर के लिए 90 के माध्यम से काउंटरक्लॉक वार और पश्चिम में 180 के लिए और पूर्व में 270 दक्षिण से 360 डिग्री पूर्व में) । मुझे अंतरंग बिंदु के निर्देशांक जानने की जरूरत है।

कुछ हद तक भ्रमित (मेरे लिए) गणितीय लेकिन अनुमानित सटीक उत्तर Finding points on a rectangle at a given angle पर मुझे निम्नलिखित कोड का प्रयास करने का नेतृत्व किया, लेकिन यह ठीक से काम नहीं करता है। यह प्रश्न उस के समान है, लेकिन मैं सामान्य गणितीय प्रतिक्रिया के बजाय एक सही उद्देश्य-सी/आईओएस विधि की तलाश में हूं।

मुझे लगता है कि कोड समस्या का एक हिस्सा इनपुट (नकारात्मक संख्या की कोई संभावना नहीं के साथ रेडियन में) एकल 0 करने के लिए 360 डिग्री कोण का उपयोग कर के साथ क्या करना है, लेकिन अन्य समस्याओं होने की संभावना नहीं है। नीचे दिया गया कोड अधिकतर the answer from belisarius में परिभाषित नोटेशन का उपयोग करता है, जिसमें परिभाषित चार क्षेत्रों में से प्रत्येक के लिए अंतरण बिंदुओं की गणना करने के मेरे प्रयास शामिल हैं।

इस कोड को मेरी UIImageView उपवर्ग में है:

- (CGPoint) startingPointGivenAngleInDegrees:(double)angle { 
    double angleInRads = angle/180.0*M_PI; 
    float height = self.frame.size.height; 
    float width = self.frame.size.width; 
    float x0 = self.center.x; 
    float y0 = self.center.y; 
    // region 1 
    if (angleInRads >= -atan2(height, width) && angleInRads <= atan2(height, width)) { 
     return CGPointMake(x0 + width/2, y0 + width/2 * tan(angleInRads)); 
    } 
    // region 2 
    if (angleInRads >= atan2(height, width) && angleInRads <= M_PI - atan2(height, width)) { 
     return CGPointMake(x0 + height/(2*tan(angleInRads)),y0+height/2); 
    } 
    // region 3 
    if (angleInRads >= M_PI - atan2(height, width) && angleInRads <= M_PI + atan2(height, width)) { 
     return CGPointMake(x0 - width/2, y0 + width/2 * tan(angleInRads)); 
    } 
    // region 4 
    return CGPointMake(x0 + height/(2*tan(angleInRads)),y0-height/2);  
} 

उत्तर

17

अपने कोड डिबगिंग के बजाय, मैं तो बस के बारे में समझाएंगे मैं यह कैसे करना होगा।

सबसे पहले, कुछ शब्दों। आइए फ्रेम की आधा ऊंचाई के रूप में xRadius फ्रेम की आधा चौड़ाई, और yRadius परिभाषित करें।

अब फ्रेम के चार किनारों पर विचार करें, और उन्हें अनंत रेखाओं के रूप में विस्तारित करें। फ्रेम के केंद्र निर्देशांक पर है -

diagram of rectangle with overlaid line

मान लीजिए कि फ्रेम मूल पर केंद्रित है दो: उन चार पंक्तियों के शीर्ष पर, एक लाइन है कि आपके द्वारा निर्दिष्ट कोण पर फ्रेम के केंद्र के माध्यम से गुजरता रखना (0,0)। हम आसानी से गणना कर सकते हैं कि विकर्ण रेखा फ्रेम के दाहिने किनारे को छेड़छाड़ करती है: निर्देशांक (xRadius, xRadius * tan(angle)) हैं। और हम आसानी से गणना कर सकते हैं कि विकर्ण रेखा फ्रेम के शीर्ष किनारे को छेड़छाड़ करती है: निर्देशांक (-yRadius/tan(angle), -yRadius) हैं।

(क्यों हम शीर्ष बढ़त चौराहे के लिए निर्देशांक नकारना करते हैं? क्योंकि UIView समन्वय प्रणाली सामान्य गणितीय समन्वय प्रणाली से फ़्लिप किया गया है। गणित में, y पृष्ठ के शीर्ष पर वृद्धि समन्वय करता है। एक UIView, वाई में निर्देशांक दृश्य के नीचे की ओर बढ़ते हैं।)

तो हम फ्रेम के दाहिने किनारे के साथ लाइन के चौराहे की गणना कर सकते हैं। यदि वह चौराहे फ्रेम के बाहर है, तो हम जानते हैं कि लाइन को शीर्ष किनारे को से पहले छेड़छाड़ करना चाहिए, यह दाएं किनारे को छेड़छाड़ करता है। हम कैसे बताएंगे कि दाएं किनारे का चौराहे सीमा से बाहर है या नहीं? यदि इसका वाई समन्वय (xRadius * tan(angle)) yRadius से अधिक है (या -yRadius से कम), तो यह सीमा से बाहर है।

तो यह सब एक साथ एक विधि में डालने के लिए, हम कंप्यूटिंग xRadius और yRadius से शुरू:

- (CGPoint)radialIntersectionWithConstrainedRadians:(CGFloat)radians { 
    // This method requires 0 <= radians < 2 * π. 

    CGRect frame = self.frame; 
    CGFloat xRadius = frame.size.width/2; 
    CGFloat yRadius = frame.size.height/2; 

फिर हम गणना y सही बढ़त के साथ चौराहे के समन्वय:

CGPoint pointRelativeToCenter; 
    CGFloat tangent = tanf(radians); 
    CGFloat y = xRadius * tangent; 

हम जांचते हैं कि चौराहे फ्रेम में है:

if (fabsf(y) <= yRadius) { 

एक बार जब हम जानते हैं कि यह फ्रेम में है, तो हमें यह पता लगाना होगा कि क्या हम दाएं किनारे या बाएं किनारे के साथ चौराहे चाहते हैं। यदि कोण π/2 (9 0 डिग्री) से कम या 3π/2 (270 डिग्री) से अधिक है, तो हम दाएं किनारे चाहते हैं। अन्यथा हम बाएं किनारे चाहते हैं।

 if (radians < (CGFloat)M_PI_2 || radians > (CGFloat)(M_PI + M_PI_2)) { 
      pointRelativeToCenter = CGPointMake(xRadius, y); 
     } else { 
      pointRelativeToCenter = CGPointMake(-xRadius, -y); 
     } 

y दाहिने किनारे चौराहे • का समन्वय हैं * था बाहर के सीमा, हम गणना एक्स निचले किनारे के साथ चौराहे के समन्वय।

} else { 
     CGFloat x = yRadius/tangent; 

अगला हम यह पता लगाते हैं कि हम शीर्ष किनारे या नीचे किनारे चाहते हैं या नहीं। यदि कोण π (180 डिग्री) से कम है, तो हम नीचे किनारे चाहते हैं। अन्यथा, हम शीर्ष किनारे चाहते हैं।

 if (radians < (CGFloat)M_PI) { 
      pointRelativeToCenter = CGPointMake(x, yRadius); 
     } else { 
      pointRelativeToCenter = CGPointMake(-x, -yRadius); 
     } 
    } 

अंत में, हम फ्रेम के वास्तविक केंद्र द्वारा गणना बिंदु को ऑफ़सेट करते हैं और इसे वापस कर देते हैं। यहाँ

return CGPointMake(pointRelativeToCenter.x + CGRectGetMidX(frame), 
     pointRelativeToCenter.y + CGRectGetMidY(frame)); 
} 

टेस्ट परियोजना: https://github.com/mayoff/stackoverflow-radial-intersection

इस तरह लग रहा है:

edgepoint screen shot

+0

शानदार! धन्यवाद। मुझे इसके साथ कुछ परेशानी थी क्योंकि मेरे मामले में मुझे एहसास नहीं हुआ कि मुझे अपने UIImageview उपclass (अन्य नौसिखियों के लिए यहां आने वाले) में [self.superview convertPoint: thepoint toView: self] करना था। –

+0

शानदार जवाब! – mrvincenzo

+0

मैं आपके कोड का अध्ययन कर रहा हूं जो उत्कृष्ट है, यह समझने की कोशिश कर रहा है कि क्या करना है यदि मैं छवि को घुमाता हूं और अभी भी किनारे का पता लगाना चाहता हूं? कोई विचार? – flooie

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