Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 获取沿贝塞尔路径的任意点_Objective C_Cocoa_Drawing_Nsbezierpath - Fatal编程技术网

Objective c 获取沿贝塞尔路径的任意点

Objective c 获取沿贝塞尔路径的任意点,objective-c,cocoa,drawing,nsbezierpath,Objective C,Cocoa,Drawing,Nsbezierpath,对于我正在编写的程序,我需要能够跟踪对象必须沿着的虚拟线(不是直线)。我想用NSBezierPath来画这条线,但是我找不到一种方法来获得这条线上的任何点,我必须这样做,这样我才能沿着这条线移动对象 有人能建议一种沿着NSBezierPath查找点的方法吗?如果这是不可能的,有人能建议一种方法来做上述工作吗?编辑:下面的代码仍然是准确的,但有更快的方法来计算它。见和 有两种方法可以做到这一点。如果只需要沿直线移动某些对象,请使用CAKeyframeAnimation。这非常简单,您不需要计算点

对于我正在编写的程序,我需要能够跟踪对象必须沿着的虚拟线(不是直线)。我想用
NSBezierPath
来画这条线,但是我找不到一种方法来获得这条线上的任何点,我必须这样做,这样我才能沿着这条线移动对象

有人能建议一种沿着
NSBezierPath
查找点的方法吗?如果这是不可能的,有人能建议一种方法来做上述工作吗?

编辑:下面的代码仍然是准确的,但有更快的方法来计算它。见和


有两种方法可以做到这一点。如果只需要沿直线移动某些对象,请使用
CAKeyframeAnimation
。这非常简单,您不需要计算点

另一方面,如果你真的因为某种原因需要知道这一点,你必须自己计算贝塞尔。例如,您可以从中提取第18章的示例代码。(它是为iOS编写的,但同样适用于Mac。)查看
CurvyTextView.m

给定控制点
P0
P3
,以及0和1之间的偏移量(见下文),
点foroffset:
将为您提供沿路径的点:

static double Bezier(double t, double P0, double P1, double P2,
                     double P3) {
  return 
                   pow(1-t, 3) *     P0
     + 3 *         pow(1-t, 2) * t * P1
     + 3 * (1-t) * pow(t,   2) *     P2
     +             pow(t,   3) *     P3;
}

- (CGPoint)pointForOffset:(double)t {
  double x = Bezier(t, P0_.x, P1_.x, P2_.x, P3_.x);
  double y = Bezier(t, P0_.y, P1_.y, P2_.y, P3_.y);
  return CGPointMake(x, y);
}
注意:此代码违反了我的基本规则之一,即始终使用访问器而不是直接访问IVAR。这是因为在这种情况下,它会被调用数千次,而消除方法调用会对性能产生重大影响

“补偿”不是一件需要解决的小事。它不会沿着曲线线性前进。如果需要沿曲线均匀分布的点,则需要计算每个点的正确偏移。这是通过以下例程完成的:

// Simplistic routine to find the offset along Bezier that is
// aDistance away from aPoint. anOffset is the offset used to
// generate aPoint, and saves us the trouble of recalculating it
// This routine just walks forward until it finds a point at least
// aDistance away. Good optimizations here would reduce the number
// of guesses, but this is tricky since if we go too far out, the
// curve might loop back on leading to incorrect results. Tuning
// kStep is good start.
- (double)offsetAtDistance:(double)aDistance 
                 fromPoint:(CGPoint)aPoint
                    offset:(double)anOffset {
  const double kStep = 0.001; // 0.0001 - 0.001 work well
  double newDistance = 0;
  double newOffset = anOffset + kStep;
  while (newDistance <= aDistance && newOffset < 1.0) {
    newOffset += kStep;
    newDistance = Distance(aPoint, 
                           [self pointForOffset:newOffset]);
  }
  return newOffset;
}
//查找沿贝塞尔曲线的偏移量的简单例程
//A远离A点。anOffset是用于
//生成aPoint,省去了重新计算它的麻烦
//这个例程只是向前走,直到找到至少一个点为止
//再见。这里的良好优化将减少数量
//当然是猜测,但这是很棘手的,因为如果我们走得太远,那么
//曲线可能会循环返回,导致不正确的结果。调谐
//kStep是一个好的开始。
-(双)偏移量:(双)偏移量
fromPoint:(CGPoint)aPoint
偏移量:(双)无偏移量{
const double kStep=0.001;//0.0001-0.001工作正常
双新距离=0;
double newOffset=anOffset+kStep;
while(newDistanceEDIT):下面的代码仍然准确,但是有更快的方法来计算它。请参阅和


有两种方法可以实现这一点。如果您只需要沿直线移动某个对象,请使用
CAKeyframeAnimation
。这非常简单,您无需计算点

另一方面,如果你出于某种原因确实需要知道这一点,你必须自己计算贝塞尔。例如,你可以从中提取第18章的示例代码。(它是为iOS编写的,但同样适用于Mac。)查看
CurvyTextView.m

给定控制点
P0
P3
,以及0和1之间的偏移量(见下文),
点foroffset:
将为您提供沿路径的点:

static double Bezier(double t, double P0, double P1, double P2,
                     double P3) {
  return 
                   pow(1-t, 3) *     P0
     + 3 *         pow(1-t, 2) * t * P1
     + 3 * (1-t) * pow(t,   2) *     P2
     +             pow(t,   3) *     P3;
}

- (CGPoint)pointForOffset:(double)t {
  double x = Bezier(t, P0_.x, P1_.x, P2_.x, P3_.x);
  double y = Bezier(t, P0_.y, P1_.y, P2_.y, P3_.y);
  return CGPointMake(x, y);
}
注意:这段代码违反了我的一条基本规则,即始终使用访问器,而不是直接访问IVAR。这是因为在这段代码中,它被调用了数千次,消除方法调用会对性能产生重大影响

“偏移”不是一件容易计算的小事。它不会沿曲线线性进行。如果需要沿曲线等距分布的点,则需要计算每个点的正确偏移。这通过以下例程完成:

// Simplistic routine to find the offset along Bezier that is
// aDistance away from aPoint. anOffset is the offset used to
// generate aPoint, and saves us the trouble of recalculating it
// This routine just walks forward until it finds a point at least
// aDistance away. Good optimizations here would reduce the number
// of guesses, but this is tricky since if we go too far out, the
// curve might loop back on leading to incorrect results. Tuning
// kStep is good start.
- (double)offsetAtDistance:(double)aDistance 
                 fromPoint:(CGPoint)aPoint
                    offset:(double)anOffset {
  const double kStep = 0.001; // 0.0001 - 0.001 work well
  double newDistance = 0;
  double newOffset = anOffset + kStep;
  while (newDistance <= aDistance && newOffset < 1.0) {
    newOffset += kStep;
    newDistance = Distance(aPoint, 
                           [self pointForOffset:newOffset]);
  }
  return newOffset;
}
//查找沿贝塞尔曲线的偏移量的简单例程
//A距离A点的距离。A偏移是用于
//生成aPoint,省去了重新计算它的麻烦
//这个例程只是向前走,直到找到至少一个点为止
//A远离。良好的优化可以减少数量
//当然是猜测,但这是很棘手的,因为如果我们走得太远,那么
//曲线可能会返回,导致不正确的结果。调整
//kStep是一个好的开始。
-(双)偏移量:(双)偏移量
fromPoint:(CGPoint)aPoint
偏移量:(双)无偏移量{
const double kStep=0.001;//0.0001-0.001工作正常
双新距离=0;
double newOffset=anOffset+kStep;

虽然(newDistance非常感谢您的帮助!我肯定计划使用它!我还将研究这种形式的动画;从我目前阅读的内容来看,它听起来不错。顺便说一句,我在这方面做了很多工作,并显著提高了上述代码的性能。讨论在和中。我将很快发布关于曲线命中测试和优化霓虹灯。非常感谢您的帮助!我肯定计划使用它!我还将研究这种形式的动画;从我目前阅读的内容来看,它听起来不错。顺便说一句,我在这方面做了很多工作,并显著提高了上述代码的性能。讨论在和中。我将很快发布关于曲线命中率的讨论对霓虹灯进行优化。