2013-05-26 8 views
5

मेरे पास एक ऐप है जो UIView में एक बेजियर वक्र खींचता है और जब मैं समझता हूं कि एक्स को पहले से जोड़ता है तो मुझे एक्स अंतरण की आवश्यकता होती है, जैसा कि मैं समझता हूं, ऐसा कोई तरीका नहीं है UIBezierPath का सीधे एक बिंदु खोजें लेकिन आप CGPath के बिंदु का पता लगा सकते हैं।पथ पर एक बिंदु ढूंढना

सबसे पहले, अगर मैं अपने UIBezierPath (जैसा कि मैंने अपने कोड में किया है) "स्ट्रोक" है, तो क्या यह वास्तव में एक CGPath बना रहा है या क्या मुझे इसे वास्तव में CGPath में परिवर्तित करने के लिए और कदम उठाने की आवश्यकता है?

दूसरा, मैं वाई

के लिए मूल्य प्रदान करके घटता एक्स पर एक दूसरे को काटना लगाना चाहते हैं

मेरे इरादे स्वचालित रूप से वाई के दिए गए मूल्य के लिए एक्स गणना करने के लिए उपयोगकर्ता स्लाइडर (जो वक्र चाल से चलता है के रूप में है क्रमशः बाएं या दाएं)।

मेरा प्रारंभिक प्रदर्शन।

My starting display

जब मैं वर्तमान में स्लाइडर को क्या होता है।

What happens when I currently adjust slider

मैं क्या चाहता हूँ मेरा प्रदर्शन भी की तरह लग रहे।

What I want my display too look like

GraphView.h

#import <UIKit/UIKit.h> 

@interface GraphView : UIView 
{ 
    float adjust; 
    int x; 
    int y; 
} 

- (IBAction)sliderChanged:(id)sender; 
- (IBAction)yChanged:(id)sender; 

@property (weak, nonatomic) IBOutlet UISlider *sliderValue; 
@property (weak, nonatomic) IBOutlet UITextField *xValue; 
@property (weak, nonatomic) IBOutlet UITextField *yValue; 

@end 

GraphView.m

#import "GraphView.h" 

@interface GraphView() 


@end 

@implementation GraphView 

@synthesize sliderValue, xValue, yValue; 

- (id)initWithCoder:(NSCoder *)graphView 
{ 
    self = [super initWithCoder:graphView]; 
    if (self) { 
     adjust = 194; 
     y = 100; 
    } 
    return self; 
} 

- (IBAction)sliderChanged:(id)sender 
{ 
    adjust = sliderValue.value; 
    // Calcualtion of the X Value and setting of xValue.text textField goes here 
    [self setNeedsDisplay]; 
} 

- (IBAction)yChanged:(id)sender 
{ 
    y = yValue.text.intValue; 
    [self setNeedsDisplay]; 
    [self resignFirstResponder]; 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch * touch = [touches anyObject]; 
    if(touch.phase == UITouchPhaseBegan) { 
     y = yValue.text.intValue; 
     [self setNeedsDisplay]; 
     [yValue resignFirstResponder]; 
    } 
} 

- (void)drawRect:(CGRect)rect 
{ 
    UIBezierPath *lines = [[UIBezierPath alloc] init]; 
    [lines moveToPoint:CGPointMake(0, y)]; 
    [lines addLineToPoint:CGPointMake(200, y)]; 
    [lines addLineToPoint:CGPointMake(200, 280)]; 
    [lines setLineWidth:1]; 
    [[UIColor redColor] setStroke]; 
    float dashPattern[] = {2, 2}; 
    [lines setLineDash:dashPattern count:2 phase:0.0]; 
    [lines stroke]; 

    UIBezierPath *curve = [[UIBezierPath alloc] init]; 
    [curve moveToPoint:CGPointMake(0, 280)]; 
    [curve addCurveToPoint:CGPointMake(280, 0) controlPoint1:CGPointMake(adjust, 280) controlPoint2:CGPointMake(adjust, 0)]; 
    [curve setLineWidth:2]; 
    [[UIColor blueColor] setStroke]; 
    [curve stroke]; 

} 

@end 
+0

थोड़ा और आगे इस बारे में सोच करने के बाद ... मैं अगर मैं नियंत्रण बिंदुओं बेज़ियर पथ (प्रयुक्त गणना या प्रतिशत) की वक्र मैं करने के लिए होने के एक दूसरे को काटना बजाय गणना कर सकते हैं समायोजित कितना जानता था लगता है मेरे ऐप छेड़छाड़ वापस आ गया है। मुझे यकीन है कि यह एक मानक गणना/प्रतिशत है, क्या किसी को पता है कि यह गणना क्या है या इसे कहां मिलना है? –

+0

तो छेड़छाड़ की गणना करने का समाधान डी Casteljau के एल्गोरिदम होना चाहिए। मेरे पास अभी यह लागू करने का समय नहीं है, लेकिन जब मैं करता हूं तो मैं अपना समाधान पोस्ट करूंगा। एक बार मेरे पास होने के बाद, मुझे वाई के मूल्य प्रदान करके अंतरण की गणना करने के लिए अपनी स्वयं की विधि बनाने में सक्षम होना चाहिए। –

+0

वहां एक पोस्ट था जिसे बाद में पाइथागोरियन के प्रमेय का उपयोग करके परेशान कर दिया गया है ... इसकी प्रतिक्रिया मेरी अगली टिप्पणी में है। –

उत्तर

6

एक घन Bézier वक्र 4 अंकों से परिभाषित किया गया है

+०१२३५१६४१०
P0 = (x0, y0) = start point, 
P1 = (x1, y1) = first control point, 
P2 = (x2, y2) = second control point, 
P3 = (x3, y3) = end point, 

और सभी बिंदुओं

x(t) = (1-t)^3 * x0 + 3*t*(1-t)^2 * x1 + 3*t^2*(1-t) * x2 + t^3 * x3 
y(t) = (1-t)^3 * y0 + 3*t*(1-t)^2 * y1 + 3*t^2*(1-t) * y2 + t^3 * y3 

के होते हैं जहां t0 से 1 को चलाता है।

इसलिए, वाई की दी गई मूल्य के लिए गणना करने के लिए एक्स, आपको पहले एक पैरामीटर मान की गणना करने के T ऐसी है कि 0 <= T <= 1 और

Y = (1-T)^3 * y0 + 3*T*(1-T)^2 * y1 + 3*T^2*(1-T) * y2 + T^3 * y3  (1) 

और उसके बाद की गणना एक्स के साथ समन्वय स्थापित है

X = (1-T)^3 * y0 + 3*T*(1-T)^2 * y1 + 3*T^2*(1-T) * y2 + T^3 * y3  (2) 

तो आपको T के लिए क्यूबिक समीकरण (1) को हल करना होगा और मान को (2) में बदलना होगा।

घन समीकरण स्पष्ट रूप से हल किया जा सकता (http://en.wikipedia.org/wiki/Bisection_method का उपयोग कर उदाहरण के लिए) (देखें उदाहरण के लिए http://en.wikipedia.org/wiki/Cubic_function) या iteratively।

सामान्य रूप से, एक घन समीकरण में तीन अलग-अलग समाधान हो सकते हैं। अपने ठोस मामले में हम

P0 = (0, 280), P1 = (adjust, 280), P3 = (adjust, 0), P4 = (280, 0) 

है ताकि समीकरण (1) हो जाता है

Y = (1-T)^3 * 280 + 3*T*(1-T)^2 * 280 

जो

Y/280 = 1 - 3*T^2 + 2*T^3 (3) 

की (3) एक सख्ती से कम हो रही है दाहिने हाथ की ओर करने के लिए सरल अंतराल [0, 1] में T का कार्य, इसलिए यह देखना मुश्किल नहीं है कि (3) 0 <= Y <= 280 पर बिल्कुल एक समाधान है। इस समाधान को (2) में वांछित एक्स मान देता है।

+0

के लिए अपने मूल्य का आधा जानता हूं बहुत प्रभावशाली! बहुत बढ़िया जवाब! इसे लागू करने के लिए इंतजार नहीं कर सकता! –

+0

मैंने पैरामीट्रिक गणना का उपयोग किया है लेकिन मैं एक छोटी सी समस्या में भाग रहा हूं। यदि मैं अपने वाई मान को वाई अक्ष पर 75 पर सेट करता हूं जो 100 पिक्सेल है और मेरे टी मान को 75% पर सेट करने से पहले यह 75% लाइन पर निर्देशांक देता है और 75 के वाई मान पर स्थित मूल्य नहीं है। कोई सुझाव? –

+0

@ShannonBuckland: आपको टी * के लिए समीकरण (3) को हल करना होगा। तो आपको एक मान टी खोजना होगा जैसे कि 1 + 3 * टी^2 + टी^3 = 75/100 = 0.75। समाधान (इस विशेष मामले में) लगभग टी = 0.3045 है। –

0

मुझे थोड़ी देर लग गई लेकिन नीचे दिया गया कोड यह है कि मैंने बेजियर वक्र पर एक बिंदु खोजने का हल किया। गणित केवल संभावित 3 मानों में से एक पाता है, इसलिए मुझे संदेह है कि यदि एक से अधिक है तो यह असफल हो जाएगा, लेकिन मेरे परिस्थिति में मेरे बेजियर में केवल एक समाधान होना चाहिए क्योंकि मेरे वक्र को एक ही बार या एक से अधिक विमान को कभी भी पार नहीं करना चाहिए । मैं जो साझा करता हूं उसे साझा करना चाहता था और मैं किसी भी प्रश्न, टिप्पणियों या सुझावों का स्वागत करता हूं।

#import "Calculation.h" 

@implementation Calculation 

@synthesize a, b, c, d, xy; 

- (float) calc 
{ 

    float squareRootCalc = 
    sqrt(
    6*pow(xy,2)*b*d 
    +4*a*pow(c,3) 
    -3*pow(b,2)*pow(c,2) 
    +9*pow(xy,2)*pow(c,2) 
    -6*a*c*b*d 
    +6*a*xy*c*b 
    -18*pow(xy,2)*b*c 
    +6*a*pow(xy,2)*c 
    -12*a*xy*pow(c,2) 
    -2*pow(a,2)*xy*d 
    +pow(a,2)*pow(d,2) 
    +4*pow(b,3)*d 
    +pow(xy,2)*pow(d,2) 
    -4*pow(b,3)*xy 
    -4*pow(c,3)*xy 
    +pow(a,2)*pow(xy,2) 
    +6*c*b*d*xy 
    +6*a*c*d*xy 
    +6*a*b*d*xy 
    -12*pow(b,2)*d*xy 
    +6*xy*c*pow(b,2) 
    +6*xy*b*pow(c,2) 
    -2*a*pow(xy,2)*d 
    -2*a*xy*pow(d,2) 
    -6*c*d*pow(xy,2) 
    +9*pow(xy,2)*pow(b,2) 
    -6*a*pow(xy,2)*b) 
    ; 

    float aCalc = 24*c*d*xy + 24*a*pow(c,2) - 36*xy*pow(c,2) + 4 * squareRootCalc * a; 

    float bCalc = -12 * squareRootCalc * b; 

    float cCalc = 12 * squareRootCalc * c; 

    float dCalc = -4 * squareRootCalc * d; 


    float xyCalc = 
    24*xy*a*b 
    -24*xy*b*d 
    -12*b*a*d 
    -12*c*a*d 
    -12*c*b*d 
    +8*xy*a*d 
    +8*pow(b,3) 
    +8*pow(c,3) 
    +4*pow(a,2)*d 
    +24*pow(b,2)*d 
    -4*xy*pow(a,2) 
    -4*xy*pow(d,2) 
    +4*a*pow(d,2) 
    -12*c*pow(b,2) 
    -12*b*pow(c,2) 
    -12*a*b*c 
    -24*xy*a*c 
    +72*xy*c*b 
    -36*xy*pow(b,2) 
    ; 

    float cubeRootCalc = cbrt(aCalc + bCalc + cCalc + dCalc + xyCalc); 

    float denomCalc = (a-3*b+3*c-d); 

    float secOneCalc = 0.5 * cubeRootCalc/denomCalc; 

    float secTwoCalc = -2 * ((a*c - a*d - pow(b,2) + c*b + b*d - pow(c,2))/(denomCalc * cubeRootCalc)); 

    float secThreeCalc = (a - 2*b + c)/denomCalc; 

    return secOneCalc + secTwoCalc + secThreeCalc; 


} 

- (Calculation *) initWithA:(float)p0 andB:(float)p1 andC:(float)p2 andD:(float)p3 andXy:(float)xyValue 
{ 
    self = [super init]; 

    if (self) { 
     [self setA:p0]; 
     [self setB:p1]; 
     [self setC:p2]; 
     [self setD:p3]; 
     [self setXy:xyValue]; 
    } 
    return self; 
} 

- (void) setA:(float)p0 andB:(float)p1 andC:(float)p2 andD:(float)p3 andXy:(float)xyValue 
{ 
    [self setA:p0]; 
    [self setB:p1]; 
    [self setC:p2]; 
    [self setD:p3]; 
    [self setXy:xyValue]; 
} 

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