|
@@ -43,8 +43,6 @@ |
|
@@ -43,8 +43,6 @@ |
43
|
|
43
|
|
44
|
contents = aContents;
|
44
|
contents = aContents;
|
45
|
|
45
|
|
46
|
- path = CGPathCreateMutable();
|
|
|
47
|
-
|
|
|
48
|
lineWidth = 100.0f;
|
46
|
lineWidth = 100.0f;
|
49
|
drawingMode = kCGPathFillStroke;
|
47
|
drawingMode = kCGPathFillStroke;
|
50
|
lineColor = [UIColor blackColor];
|
48
|
lineColor = [UIColor blackColor];
|
|
@@ -52,6 +50,7 @@ |
|
@@ -52,6 +50,7 @@ |
52
|
self.masksToBounds = NO;
|
50
|
self.masksToBounds = NO;
|
53
|
|
51
|
|
54
|
scaleLineWidth = YES;
|
52
|
scaleLineWidth = YES;
|
|
|
53
|
+ boundsInMercators = CGRectZero;
|
55
|
// self.frame = CGRectMake(100, 100, 100, 100);
|
54
|
// self.frame = CGRectMake(100, 100, 100, 100);
|
56
|
// [self setNeedsDisplayOnBoundsChange:YES];
|
55
|
// [self setNeedsDisplayOnBoundsChange:YES];
|
57
|
|
56
|
|
|
@@ -68,6 +67,8 @@ |
|
@@ -68,6 +67,8 @@ |
68
|
CGPathRelease(path);
|
67
|
CGPathRelease(path);
|
69
|
[self setLineColor:nil];
|
68
|
[self setLineColor:nil];
|
70
|
[self setFillColor:nil];
|
69
|
[self setFillColor:nil];
|
|
|
70
|
+ [points release];
|
|
|
71
|
+ points = nil;
|
71
|
|
72
|
|
72
|
[super dealloc];
|
73
|
[super dealloc];
|
73
|
}
|
74
|
}
|
|
@@ -80,26 +81,53 @@ |
|
@@ -80,26 +81,53 @@ |
80
|
- (void) recalculateGeometry
|
81
|
- (void) recalculateGeometry
|
81
|
{
|
82
|
{
|
82
|
float scale = [[contents mercatorToScreenProjection] scale];
|
83
|
float scale = [[contents mercatorToScreenProjection] scale];
|
83
|
- // The bounds are actually in mercators...
|
|
|
84
|
- CGRect boundsInMercators = CGPathGetBoundingBox(path);
|
|
|
85
|
- boundsInMercators.origin.x -= lineWidth;
|
|
|
86
|
- boundsInMercators.origin.y -= lineWidth;
|
|
|
87
|
- boundsInMercators.size.width += 2*lineWidth;
|
|
|
88
|
- boundsInMercators.size.height += 2*lineWidth;
|
84
|
+ float scaledLineWidth;
|
|
|
85
|
+ CGPoint myPosition;
|
|
|
86
|
+ CGRect pixelBounds, screenBounds;
|
|
|
87
|
+ float offset;
|
|
|
88
|
+ const float outset = 100.0f; // provides a buffer off screen edges for when path is scaled or moved
|
|
|
89
|
+
|
|
|
90
|
+ scaledLineWidth = lineWidth;
|
|
|
91
|
+ if(!scaleLineWidth) {
|
|
|
92
|
+ renderedScale = [contents scale];
|
|
|
93
|
+ scaledLineWidth *= renderedScale;
|
|
|
94
|
+ }
|
|
|
95
|
+ pixelBounds = CGRectInset(boundsInMercators, -scaledLineWidth, -scaledLineWidth);
|
89
|
|
96
|
|
90
|
- CGRect pixelBounds = RMScaleCGRectAboutPoint(boundsInMercators, 1.0f / scale, CGPointMake(0,0));
|
97
|
+ pixelBounds = RMScaleCGRectAboutPoint(pixelBounds, 1.0f / scale, CGPointZero);
|
91
|
|
98
|
|
92
|
-// NSLog(@"old bounds: %f %f %f %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height);
|
|
|
93
|
- self.bounds = pixelBounds;
|
|
|
94
|
-// NSLog(@"new bounds: %f %f %f %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height);
|
99
|
+ // Clip bound rect to screen bounds.
|
|
|
100
|
+ // If bounds are not clipped, they won't display when you zoom in too much.
|
|
|
101
|
+ myPosition = [[contents mercatorToScreenProjection] projectXYPoint: origin];
|
|
|
102
|
+ screenBounds = [contents screenBounds];
|
95
|
|
103
|
|
96
|
-// NSLog(@"old position: %f %f", self.position.x, self.position.y);
|
|
|
97
|
- self.position = [[contents mercatorToScreenProjection] projectXYPoint: origin];
|
|
|
98
|
-// NSLog(@"new position: %f %f", self.position.x, self.position.y);
|
104
|
+ // Clip top
|
|
|
105
|
+ offset = myPosition.y + pixelBounds.origin.y - screenBounds.origin.y + outset;
|
|
|
106
|
+ if(offset < 0.0f) {
|
|
|
107
|
+ pixelBounds.origin.y -= offset;
|
|
|
108
|
+ pixelBounds.size.height += offset;
|
|
|
109
|
+ }
|
|
|
110
|
+ // Clip left
|
|
|
111
|
+ offset = myPosition.x + pixelBounds.origin.x - screenBounds.origin.x + outset;
|
|
|
112
|
+ if(offset < 0.0f) {
|
|
|
113
|
+ pixelBounds.origin.x -= offset;
|
|
|
114
|
+ pixelBounds.size.width += offset;
|
|
|
115
|
+ }
|
|
|
116
|
+ // Clip bottom
|
|
|
117
|
+ offset = myPosition.y + pixelBounds.origin.y + pixelBounds.size.height - screenBounds.origin.y - screenBounds.size.height - outset;
|
|
|
118
|
+ if(offset > 0.0f) {
|
|
|
119
|
+ pixelBounds.size.height -= offset;
|
|
|
120
|
+ }
|
|
|
121
|
+ // Clip right
|
|
|
122
|
+ offset = myPosition.x + pixelBounds.origin.x + pixelBounds.size.width - screenBounds.origin.x - screenBounds.size.width - outset;
|
|
|
123
|
+ if(offset > 0.0f) {
|
|
|
124
|
+ pixelBounds.size.width -= offset;
|
|
|
125
|
+ }
|
99
|
|
126
|
|
100
|
-// NSLog(@"Old anchor point %f %f", self.anchorPoint.x, self.anchorPoint.y);
|
127
|
+ self.position = myPosition;
|
|
|
128
|
+ self.bounds = pixelBounds;
|
101
|
self.anchorPoint = CGPointMake(-pixelBounds.origin.x / pixelBounds.size.width,-pixelBounds.origin.y / pixelBounds.size.height);
|
129
|
self.anchorPoint = CGPointMake(-pixelBounds.origin.x / pixelBounds.size.width,-pixelBounds.origin.y / pixelBounds.size.height);
|
102
|
-// NSLog(@"new anchor point %f %f", self.anchorPoint.x, self.anchorPoint.y);
|
130
|
+ [self setNeedsDisplay];
|
103
|
}
|
131
|
}
|
104
|
|
132
|
|
105
|
- (void) addLineToXY: (RMXYPoint) point
|
133
|
- (void) addLineToXY: (RMXYPoint) point
|
|
@@ -110,12 +138,12 @@ |
|
@@ -110,12 +138,12 @@ |
110
|
|
138
|
|
111
|
if (points == nil)
|
139
|
if (points == nil)
|
112
|
{
|
140
|
{
|
113
|
- points = [[NSMutableArray alloc] init];
|
|
|
114
|
- [points addObject:value];
|
141
|
+ points = [[NSMutableArray alloc] initWithObjects:value, nil];
|
115
|
origin = point;
|
142
|
origin = point;
|
116
|
|
143
|
|
117
|
self.position = [[contents mercatorToScreenProjection] projectXYPoint: origin];
|
144
|
self.position = [[contents mercatorToScreenProjection] projectXYPoint: origin];
|
118
|
// NSLog(@"screen position set to %f %f", self.position.x, self.position.y);
|
145
|
// NSLog(@"screen position set to %f %f", self.position.x, self.position.y);
|
|
|
146
|
+ path = CGPathCreateMutable();
|
119
|
CGPathMoveToPoint(path, NULL, 0.0f, 0.0f);
|
147
|
CGPathMoveToPoint(path, NULL, 0.0f, 0.0f);
|
120
|
}
|
148
|
}
|
121
|
else
|
149
|
else
|
|
@@ -127,9 +155,11 @@ |
|
@@ -127,9 +155,11 @@ |
127
|
|
155
|
|
128
|
CGPathAddLineToPoint(path, NULL, point.x, -point.y);
|
156
|
CGPathAddLineToPoint(path, NULL, point.x, -point.y);
|
129
|
|
157
|
|
|
|
158
|
+ // The bounds are actually in mercators...
|
|
|
159
|
+ boundsInMercators = CGPathGetBoundingBox(path);
|
|
|
160
|
+
|
130
|
[self recalculateGeometry];
|
161
|
[self recalculateGeometry];
|
131
|
}
|
162
|
}
|
132
|
- [self setNeedsDisplay];
|
|
|
133
|
}
|
163
|
}
|
134
|
|
164
|
|
135
|
- (void) addLineToScreenPoint: (CGPoint) point
|
165
|
- (void) addLineToScreenPoint: (CGPoint) point
|
|
@@ -148,18 +178,24 @@ |
|
@@ -148,18 +178,24 @@ |
148
|
|
178
|
|
149
|
- (void)drawInContext:(CGContextRef)theContext
|
179
|
- (void)drawInContext:(CGContextRef)theContext
|
150
|
{
|
180
|
{
|
151
|
- renderedScale = [contents scale];
|
181
|
+ float scale, scaledLineWidth;
|
152
|
|
182
|
|
153
|
// CGContextFillRect(theContext, self.bounds);//CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
|
183
|
// CGContextFillRect(theContext, self.bounds);//CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
|
154
|
|
184
|
|
155
|
- float scale = 1.0f / [contents scale];
|
185
|
+ renderedScale = [contents scale];
|
|
|
186
|
+ scale = 1.0f / renderedScale;
|
|
|
187
|
+
|
|
|
188
|
+ scaledLineWidth = lineWidth;
|
|
|
189
|
+ if(!scaleLineWidth) {
|
|
|
190
|
+ scaledLineWidth *= renderedScale;
|
|
|
191
|
+ }
|
156
|
|
192
|
|
157
|
CGContextScaleCTM(theContext, scale, scale);
|
193
|
CGContextScaleCTM(theContext, scale, scale);
|
158
|
|
194
|
|
159
|
CGContextBeginPath(theContext);
|
195
|
CGContextBeginPath(theContext);
|
160
|
CGContextAddPath(theContext, path);
|
196
|
CGContextAddPath(theContext, path);
|
161
|
|
197
|
|
162
|
- CGContextSetLineWidth(theContext, lineWidth);
|
198
|
+ CGContextSetLineWidth(theContext, scaledLineWidth);
|
163
|
CGContextSetStrokeColorWithColor(theContext, [lineColor CGColor]);
|
199
|
CGContextSetStrokeColorWithColor(theContext, [lineColor CGColor]);
|
164
|
CGContextSetFillColorWithColor(theContext, [fillColor CGColor]);
|
200
|
CGContextSetFillColorWithColor(theContext, [fillColor CGColor]);
|
165
|
CGContextDrawPath(theContext, drawingMode);
|
201
|
CGContextDrawPath(theContext, drawingMode);
|
|
@@ -180,7 +216,6 @@ |
|
@@ -180,7 +216,6 @@ |
180
|
{
|
216
|
{
|
181
|
lineWidth = newLineWidth;
|
217
|
lineWidth = newLineWidth;
|
182
|
[self recalculateGeometry];
|
218
|
[self recalculateGeometry];
|
183
|
- [self setNeedsDisplay];
|
|
|
184
|
}
|
219
|
}
|
185
|
|
220
|
|
186
|
- (CGPathDrawingMode) drawingMode
|
221
|
- (CGPathDrawingMode) drawingMode
|
|
@@ -220,16 +255,28 @@ |
|
@@ -220,16 +255,28 @@ |
220
|
}
|
255
|
}
|
221
|
}
|
256
|
}
|
222
|
|
257
|
|
|
|
258
|
+- (BOOL)scaleLineWidth
|
|
|
259
|
+{
|
|
|
260
|
+ return scaleLineWidth;
|
|
|
261
|
+}
|
|
|
262
|
+
|
|
|
263
|
+- (void)setScaleLineWidth:(BOOL)newState
|
|
|
264
|
+{
|
|
|
265
|
+ scaleLineWidth = newState;
|
|
|
266
|
+ [self recalculateGeometry];
|
|
|
267
|
+}
|
|
|
268
|
+
|
|
|
269
|
+- (void)moveBy: (CGSize) delta {
|
|
|
270
|
+ [super moveBy:delta];
|
|
|
271
|
+
|
|
|
272
|
+ [self recalculateGeometry];
|
|
|
273
|
+}
|
|
|
274
|
+
|
223
|
- (void)zoomByFactor: (float) zoomFactor near:(CGPoint) pivot
|
275
|
- (void)zoomByFactor: (float) zoomFactor near:(CGPoint) pivot
|
224
|
{
|
276
|
{
|
225
|
[super zoomByFactor:zoomFactor near:pivot];
|
277
|
[super zoomByFactor:zoomFactor near:pivot];
|
226
|
|
278
|
|
227
|
- float newScale = [contents scale];
|
|
|
228
|
- if (newScale / renderedScale >= 2.0f
|
|
|
229
|
- || newScale / renderedScale <= 0.4f)
|
|
|
230
|
- {
|
|
|
231
|
- [self setNeedsDisplay];
|
|
|
232
|
- }
|
279
|
+ [self recalculateGeometry];
|
233
|
}
|
280
|
}
|
234
|
|
281
|
|
235
|
@end |
282
|
@end |