高效的图纸存储方法?
我正在开发一个包含几个类的基本绘图应用程序。其中之一是“Line”类,它存储用户可以绘制的线条上的一些信息。当用户在屏幕上拖动时,手指的每次移动都会创建一条线,因此会跟随手指绘制一条线。我将所有线条对象存储在 NSArray 中,并在每次发生变化时重新绘制。然而,由于数组不断变大,最终开始变慢。有没有什么方法可以只绘制新的线条,或者有更好的线条存储机制?
编辑: 阅读下面的答案,但 setNeedsDisplayInRect:
似乎不起作用。我这样称呼它:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *t in touches) {
//add line to array w/ x and y values from touch
[self setNeedsDisplayInRect:[self rectForLine:line]];
}
}
-(CGRect)rectForLine:(Line*)line {
CGFloat x1 = [line begin].x;
CGFloat y1 = [line begin].y;
CGFloat x2 = [line end].x;
CGFloat y2 = [line end].y;
CGFloat originX = (x1>x2) ? x1 : x2;
CGFloat originY = (y1<y2) ? y1 : y2;
CGFloat diffX = ((x1>x2) ? x1 : x2) - originX;
CGFloat diffY = ((y1>x2) ? y1 : y2) - originY;
return CGRectMake(originX, originY, diffX, diffY);
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 10.0);
CGContextSetLineCap(context, kCGLineCapRound);
//[[UIColor blackColor] set];
for (Line *line in completeLines) {
if (CGRectContainsPoint(rect, [line begin]) && CGRectContainsPoint(rect, [line end])) {
//draw line onto the screen
}
}
I'm developing a basic drawing app that has a few classes. One of these is a "Line" class that stores some info on a line the user can draw. When the user drags round the screen, a line is created for each movement of their finger, so a line is drawn following their finger. I store all the line objects in an NSArray and redraw each time something changes. However, since the array just keeps getting bigger, and eventually starts to slow down. Is there any way to just draw the new lines, or a better storage mechanism for the lines?
EDIT:
Read the answer below, but setNeedsDisplayInRect:
doesn't seem to be working. I am calling it like so:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *t in touches) {
//add line to array w/ x and y values from touch
[self setNeedsDisplayInRect:[self rectForLine:line]];
}
}
-(CGRect)rectForLine:(Line*)line {
CGFloat x1 = [line begin].x;
CGFloat y1 = [line begin].y;
CGFloat x2 = [line end].x;
CGFloat y2 = [line end].y;
CGFloat originX = (x1>x2) ? x1 : x2;
CGFloat originY = (y1<y2) ? y1 : y2;
CGFloat diffX = ((x1>x2) ? x1 : x2) - originX;
CGFloat diffY = ((y1>x2) ? y1 : y2) - originY;
return CGRectMake(originX, originY, diffX, diffY);
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 10.0);
CGContextSetLineCap(context, kCGLineCapRound);
//[[UIColor blackColor] set];
for (Line *line in completeLines) {
if (CGRectContainsPoint(rect, [line begin]) && CGRectContainsPoint(rect, [line end])) {
//draw line onto the screen
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果一条“线”只是数据模型中的一对点,那么这并不是减慢您速度的部分。
您的性能问题是您要重新绘制添加的每一行的整个内容,这是 O(n^2) 或非常具体的 Schlemiel-the-Painter 算法。
最简单的改进,假设您在 UIView 的
-drawRect:
内进行绘制,可能只是使包含新行的矩形无效并重新绘制。根据起点和终点,您可以创建无效的矩形以发送到-setNeedsDisplayInRect:
,然后在您的绘制矩形中,查看所有线条,并仅绘制落在该矩形内的线条。这将您的绘图性能限制在线条的大小上,并在较小程度上限制了“已经存在”的绘图。If a "line" is just a pair of points in your data model, that's not the part slowing you down.
Your perf problem is that you're redrawing the whole thing every line that gets added, which is O(n^2) or very specifically a Schlemiel-the-Painter's algorithm.
The simplest improvement, assuming you're drawing inside the
-drawRect:
of a UIView, is probably to only invalidate and redraw the rect that contains the new line. Based on the start and end points, you can create the invalid rect to send to-setNeedsDisplayInRect:
, and then in your drawRect, look at all your lines, and only draw the ones that fall inside the rect. This bounds your draw performance to the size of the lines and to a much lesser degree, the drawing that's "already there".