2

I'm trying to draw some dots connected with lines. The dot consists of the "nucleus" with orbital area around it.

enter image description here

The problem appears when I try to move those dots which gives me distorted lines: enter image description here

In my drawRect: method I iterate over an array of created dots and draw a bezier path by using lineToPoint: methods.

Dot *prevDot = nil;
NSBezierPath *line = [NSBezierPath bezierPath];
for (Dot *dot in _dots) {
    if (!prevDot) {
        [line moveToPoint:dot.position];
    } else {
        [line lineToPoint:dot.position];
    }
    prevDot = dot;
}
[line stroke];

My question is what technique should I use to implement clean line update between points once one of them is moved?

Eimantas
  • 48,927
  • 17
  • 132
  • 168
  • Is that really your loop? Your `if` doesn't make much sense. If `prevDot` is `nil`, `moveTo` its `position`?! – jscs Mar 22 '11 at 08:06
  • Sorry about that. Forgot negation .) – Eimantas Mar 22 '11 at 08:15
  • Easy to do. :) I think there may be a further mistake in your transcription, though: now you do `lineToPoint:` before you've `move`d. Shouldn't it be: `if( !prevDot ){ [line moveToPoint:dot.position]; } else { [line lineToPoint:dot.position] } prevDot = dot;`? – jscs Mar 22 '11 at 17:31
  • true, true. thanks for debugging! .) – Eimantas Mar 22 '11 at 18:38
  • Sure thing. I just implemented what you described to test it out, and I'm not getting any such distortion. Any further details you can provide? You're moving a dot by dragging the mouse, right? Are you redrawing the view's background in every `drawRect:` call? – jscs Mar 22 '11 at 20:47
  • In every draw rect I'm calling [super drawRect] with dirtyRect parameter since the view I'm dragging balls in is few thousand by few thousand (not sure if it's gonna be good performance if I redraw millions of pixels on every call. – Eimantas Mar 23 '11 at 05:08
  • Thanks for your help, Josh. I think I found the culprit - it was observed properties which were changed without proper notification. Once I removed observers - all started working! Seems a bit odd... – Eimantas Mar 23 '11 at 05:23
  • Weird. You were forgetting the `willChangeValueForKey:`/`didChangeValueForKey:`? Good luck sorting it out! – jscs Mar 23 '11 at 07:31

1 Answers1

3

Your drawing code is correct. However, you must update a larger portion of the view when it changes. It looks like you're only updating the point which moves, and not the lines. An easy fix is to call:

[myView setNeedsDisplay:YES];

whenever you change the location of the point. This will redraw the entire view. You can use other methods to more selectively update the view only where it changes, which may give you better performance.

Typically, you'd call this in a method invoked from an NSNotification sent by your data class.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • Thanks for your quick response. I do have `setNeedsDisplay:YES` in view's `mouseDragged:` method (where actual position of the dot is changed). Also - You can see in the second image that line segments in "orbit" area of the dot are correctly positioned. – Eimantas Mar 22 '11 at 06:39