6

a にベジエ曲線を描くアプリがUIViewあり、Y の値を設定するときに X の交差を見つける必要があります。まず、私が理解しているように、a のポイントを直接見つける方法はありませんが、見つけるUIBezierPathことができますのポイントCGPath

まず、(コードで行ったように) 「ストローク」した場合、UIBezierPathこれは実際に CGPath を作成していますCGPathか、それとも実際にこれを .

次に、Y の値を指定して、曲線が X で交差することを確認します。

私の意図は、ユーザーがスライダーを動かしたときに、指定された Y の値に対して X を自動的に計算することです (これにより、曲線がそれぞれ左または右に移動します)。

私のスタート画面。

私のスタート画面

現在スライダーを調整するとどうなりますか。

現在スライダーを調整するとどうなりますか

ディスプレイもどのように見せたいか。

ディスプレイもどのように見せたいか

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
4

2 に答える 2

8

3 次ベジエ曲線は 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

どこでtから まで実行さ01ます。

したがって、Y の特定の値に対して X を計算するには、最初に次の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座標を計算します

 X = (1-T)^3 * x0 + 3*T*(1-T)^2 * x1 + 3*T^2*(1-T) * x2 + T^3 * x3      (2)

したがって、3 次方程式 (1) を解いて、Tその値を (2) に代入する必要があります。

3 次方程式は明示的に (たとえばhttp://en.wikipedia.org/wiki/Cubic_functionを参照)、または反復的に (たとえば http://en.wikipedia.org/wiki/Bisection_method を使用して)解くことができます。

一般に、3 次方程式は最大 3 つの異なる解を持つことができます。あなたの具体的なケースでは、

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) の右辺はTの区間の厳密に減少する関数で[0, 1]あるため、 の場合に (3) が厳密に 1 つの解を持つことを確認することは難しくありません0 <= Y <= 280。この解を (2) に代入すると、目的の X 値が得られます。

于 2013-05-26T05:24:28.337 に答える