找到一个点的路径上 [英] finding a point on a path
问题描述
我有一个应用程序,绘制贝塞尔曲线在的UIView
,我需要找到在X相交,当我设置一个值Y.首先,据我所知,有没有一种方法,直接在 UIBezierPath
中找到一个点,但你可以找到一个点 CGPath
的。
首先,如果我中风我的 UIBezierPath
(正如我在code所做的)是这实际上创建CGPath或者我需要采取进一步步骤其实将此转换为 CGPath
?
二,我想找到的曲线相交位于X通过Y的提供的价值。
我的目的是自动地计算x为Y的定值作为用户移动滑块(而移动左或右分别曲线)。
我开始显示。
会发生什么事我目前调整滑块。
我要什么我显示太的模样。
GraphView.h
#进口< UIKit中/ UIKit.h>
@interface GraphView:UIView的
{
浮动调整;
INT X;
诠释Ÿ;
}
- (IBAction为)sliderChanged:(ID)发送;
- (IBAction为)yChanged:(ID)发送;
@property(弱,非原子)IBOutlet UISlider * sliderValue;
@property(弱,非原子)IBOutlet的UITextField *与xValue;
@property(弱,非原子)IBOutlet的UITextField * y值;
@结束
GraphView.m
#进口GraphView.h
@interface GraphView()
@结束
@implementation GraphView
@synthesize sliderValue与xValue,y值;
- (ID)initWith codeR:(NS codeR *)graphView
{
自= [超级initWith codeR:graphView]。
如果(个体经营){
调整= 194;
Y = 100;
}
回归自我;
}
- (IBAction为)sliderChanged:(ID)发件人
{
调整= sliderValue.value;
// Calcualtion的X值和xValue.text textField的的设置到这里
[自我setNeedsDisplay];
}
- (IBAction为)yChanged:(ID)发件人
{
Y = yValue.text.intValue;
[自我setNeedsDisplay];
[自resignFirstResponder]
}
- (无效)的touchesBegan:(的NSSet *)触及withEvent:(的UIEvent *)事件{
UITouch *触摸= [触摸anyObject]
如果(touch.phase == UITouchPhaseBegan){
Y = yValue.text.intValue;
[自我setNeedsDisplay];
[y值resignFirstResponder]
}
}
- (无效)的drawRect:(CGRect)RECT
{
UIBezierPath *线= [[UIBezierPath页头]初始化];
[行moveToPoint:CGPointMake(0,Y)];
[行addLineToPoint:CGPointMake(200,Y)];
[线条addLineToPoint:CGPointMake(200,280)];
[线条setLineWidth:1];
[的UIColor redColor] setStroke]。
浮dashPattern [] = {2,2};
[行setLineDash:dashPattern数:2阶段:0.0]。
[线路行程];
UIBezierPath *曲线= [[UIBezierPath页头]初始化];
[曲线moveToPoint:CGPointMake(0,280)];
[曲线addCurveToPoint:CGPointMake(280,0)controlPoint1:CGPointMake(调整,280)controlPoint2:CGPointMake(调整,0);
[曲线setLineWidth:2];
[的UIColor blueColor] setStroke]。
[曲线行程];
}
@结束
一个三次贝塞尔曲线是由4个点定义
P0 =(X0,Y0)=起点,
P1 =(X1,Y1)=第一控制点,
P2 =(X2,Y2)=第二控制点,
P3 =(X3,Y3)=结束点,
和由所有点的
X(t)=(1-T)^ 3 * X0 + 3 * T *(1-T)^ 2 * X1 + 3 * T ^ 2 *(1- T)* 2 + T ^ 3 * X3
Y(吨)=(1-t)的^ 3 * Y0 + 3 * T *(1-t)的^ 2 * Y1 + 3 *吨^ 2 *(1-t)的* Y2 + T ^ 3 * Y3
其中, T
从 0
运行到 1
。
因此,要计算x对于y的给定值,你首先要计算出一个
参数值 T
,使得 0℃= T< = 1
和
Y =(1-T)^ 3 * Y0 + 3 * T *(1-T)^ 2 * Y1 + 3 * T ^ 2 *(1-T)* Y2 + T ^ 3 * Y 3(1)
,然后计算在X与协调
X =(1-T)^ 3 * Y0 + 3 * T *(1-T)^ 2 * Y1 + 3 * T ^ 2 *(1-T)* Y2 + T ^ 3 * Y3(2)
所以,你必须解决的三次方程(1) T
并替换值代入式(2)。
三次方程可以显式(解决如见 http://en.wikipedia.org/wiki/Cubic_function )或迭代(例如使用 http://en.wikipedia.org/wiki/Bisection_method )。
在一般情况下,一个三次方程最多可以有三个不同的解决方案。在您的具体情况,我们有
P0 =(0,280),P1 =(调整,280),P3 =(调整,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] $ C $右手边C>,所以不难看出,(3)有且只有一个解决办法,如果
0℃= Y< = 280
。
代此溶液注入(2),得到所需的X值。
I have an app that draws a bezier curve in a UIView
and I need to find the X intersect when I set a value for Y. First, as I understand, there isn’t a way to find a point directly of a UIBezierPath
but you can locate a point of a CGPath
.
First, if I "stroke" my UIBezierPath
(as I have done in my code) is this actually creating a CGPath or do I need to take further steps to actually convert this to a CGPath
?
Second, I want to find the curves intersect at X by providing the value for Y.
My intention is to automatically calculate X for the given value of Y as the user moves the slider (which moves the curve left or right respectively).
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
A cubic Bézier curve is defined by 4 points
P0 = (x0, y0) = start point,
P1 = (x1, y1) = first control point,
P2 = (x2, y2) = second control point,
P3 = (x3, y3) = end point,
and consists of all points
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
where t
runs from 0
to 1
.
Therefore, to calculate X for a given value of Y, you first have to calculate a
parameter value T
such that 0 <= T <= 1
and
Y = (1-T)^3 * y0 + 3*T*(1-T)^2 * y1 + 3*T^2*(1-T) * y2 + T^3 * y3 (1)
and then compute the X coordinate with
X = (1-T)^3 * y0 + 3*T*(1-T)^2 * y1 + 3*T^2*(1-T) * y2 + T^3 * y3 (2)
So you have to solve the cubic equation (1) for T
and substitute the value into (2).
Cubic equations can be solved explicitly (see e.g. http://en.wikipedia.org/wiki/Cubic_function) or iteratively (for example using the http://en.wikipedia.org/wiki/Bisection_method).
In general, a cubic equation can have up to three different solutions. In your concrete case we have
P0 = (0, 280), P1 = (adjust, 280), P3 = (adjust, 0), P4 = (280, 0)
so that the equation (1) becomes
Y = (1-T)^3 * 280 + 3*T*(1-T)^2 * 280
which simplifies to
Y/280 = 1 - 3*T^2 + 2*T^3 (3)
The right hand side of (3) is a strictly decreasing function of T
in the interval [0, 1]
, so it is not difficult to see that (3) has exactly one solution if 0 <= Y <= 280
.
Substituting this solution into (2) gives the desired X value.
这篇关于找到一个点的路径上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!