贝塞尔曲线拟合

接上一篇Blog,这里用贝塞尔曲线来平滑多个点。 和样条插值不同,在多个点上作贝塞尔曲线的时候,曲线只穿过首尾两个点,中间的点都是作为控制点。 移动控制点,曲线也随之形变,可以造成一种拉扯的效果。在各种作图工具中,经常使用贝塞尔曲线来画曲线。一般的操作都是先画一条线段,然后可以通过拖动一个控制点来调整线段的弯曲程度。 作多点贝塞尔曲线只需要一个公式。所有的点的X值,被归一化到[0,1]区间内。 具体理论,可以参考这个页面Bézier curves。89年创建的,可有年头了。 这里还是贴代码吧。 首先需要得到X区间的总长度。 CGPoint startPt = [[_points objectAtIndex:0] CGPointValue]; CGPoint endPt = [[_points objectAtIndex:(self.pointCount – 1)] CGPointValue]; float amount = endPt.x – startPt.x; 然后就是曲线方程了,这个比样条插值要简单不少。 rank是指总的阶数,也就是实际的点数。这个函数表示n个点的贝塞尔曲线在x处的值。 这里的ux属于区间[0,1] float (^bezierSpline)(int rank, float ux) = ^(int rank, float ux) { float p = 0.0f; for (int i = 0; i < rank; i++) […]

Jon Morrow: How to Quit Your Job…

看到这类文章,总是感到很震撼,或许是因为看到了一种不同的,理想中的生活吧。 HN上的一篇文章就是这么一个励志故事。 Jon Morrow本来和我们一样,住在租来小房间里,对自己的生活不满意,总是期盼自己能有更多的时候做自己的喜欢的事情,有更多的时间陪陪家人。然后,像我们大多数人一样,他没有做什么,只是想想。直到一次车祸发生。 由于腿部14处骨折,在接下来的几个月里,Jon能做的只是忍受痛苦,还有思考自己的人生、理想和事业。他无法放弃这些,于是他辞职了。很爽快的卖掉了自己几乎所有的东西,开始写Blog。改变的过程听起来简单,但却是需要坚持的意志力。一段全身心投入事业的时间之后,Jon的事情有了起色。自己的网站每天有2000多个访问者,也应邀做了一家知名网站的编辑。 然后呢?Jon开始环视四周,考虑是不是要离开自己住的这个该死的地方。“你有没有在某一天醒来之后,发现自己其实很厌恶你住的这个地方?天气很差,邻居唠叨,你不愿意请朋友到家里来,因为它看起来一团糟”。于是,在换了工作之后,Jon离开了自己的城市。 Jon的新办公室在墨西哥的马萨特兰,度假胜地。“我在写这些的时候,我就坐在我的阳台上,看着海豚从海里跃起⋯⋯“ 是不是觉得,太爽了吧!我也是这么想的 :] 但是到此为止,Jon的故事其实还不完整。 Jon患有一种严重的疾病,从颈部一下都不能行动。疾病的疗养费用是很高的,美国的医疗制度会给予Jon资助,但是做为获得资助的条件,要求Jon每月收入自己只能保留一定数量,其余上交。这当时不是很舒服的事情了,于是Jon开始自己筹钱。一开始就放弃资助是有很大风险的。当然,这个故事有个好的结局,Jon通过帮助别人,比如教人写Blog,给一些公司提供咨询等等,有了不菲的,足以应付医疗费的收入。 很酷!不是吗? 是不是该做点什么了?嗯,我想,我们还是先冷静冷静吧,励志故事总是容易让人冲动的,但是改变却不应该是一时之勇。 毕竟我们能看到的故事都是有一个好结局的,那些随便辞掉的工作而毫无建树的家伙们是不会出来给我们讲故事的。 冷静一下,如果自己内心真的渴望改变,这些改变的动力是可以积攒的。直到有一天开始行动,凭借多年以来积蓄的力量,我们才能走的更远。

UITableViewCell的背景

Saved Blog UITableViewCell是一个很常用的View,通常我们都是直接使用它。 – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (!cell) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier] autorelease]; } cell.textLabel.text = [NSString stringWithFormat:@”Line: %d”, indexPath.row]; return cell; } 得到这个效果: 现在我们给tableViewCell加上点背景色: – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellIdentifier = @”CellIdentifier”; UITableViewCell […]

loadView的用法

UIViewController的loadView 用UIViewController有一段时间了,才发现以前对loadView的理解完全不到位。 假如我们用Xcode新建一个View-based Application,在ViewController.m中加上 – (void) loadView { NSLog(@”loadView Called”); } 再增加viewDidLoad,按照一般的情况,我们会有这样的Code – (void) viewDidLoad { [super viewDidLoad]; UIButton *customButton = [UIButton buttonWith….. …… [self.view addSubView:customButton]; } 现在打开MainWindow.xib,删掉其中的ViewController,并在AppDelegate.m的 – (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions; 里增加ViewController的初始化 viewController = [[XXXViewController alloc] init]; 编译运行就有问题了。Console中不断的输出loadView Called! 仔细的阅读loadView的文档,才知道loadView不是这么用的。 loadView在每一次使用self.view这个property,并且self.view为nil的时候被调用,用以产生一个有效的self.view。这个接口原本是为了让我们自定义view用的。在不被subclass实现的情况下,也就是[super loadView]的效果,应该就是产生了一个有效的view,也就是一个空白的view。 在上面这种情况下,loadView被实现为空(只有一条打印语句),而且我们没有通过XIB初始化ViewController,所以在viewDidLoad被执行时,self.view是为nil的。所以在执行[self.view addSubView:customButton]时,loadView被调用,用来产生一个有效的view,使得self.view不再为nil。罢特,我们错了(-_-!)。我们的loadView什么也没有做,于是就出现了上面的情形,不断的调用一个什么都不做的loadView…. 当然,我们只要在loadView中增加一句[super loadView]就没有问题了。但这并不是Cocoa的设计者所期望的。 loadView仅仅应该在开发者希望自行通过编码而不是Interface Builder定制view的时候被实现,而且不应该在其中调用[super loadView],你的loadView中应该有self.view = …这样的行为。 如果仅仅是想要在当前view上增加一些UIButton或是UILabel,应该在viewDidLoad里去做,此时不要实现自己的loadView。