Authored by Hal Mueller

incorporated Will MacKay's RMPath enhancement patch (08 Jan version). Closes Issue 29

... ... @@ -63,6 +63,7 @@
float renderedScale;
RMMapContents *contents;
CGRect boundsInMercators;
}
- (id) initWithContents: (RMMapContents*)aContents;
... ... @@ -71,10 +72,11 @@
@property CGPathDrawingMode drawingMode;
// This is the position on the map of the first point.
@property (nonatomic, assign) BOOL scaleLineWidth;
@property float lineWidth;
@property (nonatomic, assign) RMXYPoint origin;
@property (readwrite, assign) UIColor *lineColor;
@property (readwrite, assign) UIColor *fillColor;
@property (nonatomic, assign) UIColor *lineColor;
@property (nonatomic, assign) UIColor *fillColor;
- (void) addLineToXY: (RMXYPoint) point;
- (void) addLineToScreenPoint: (CGPoint) point;
... ...
... ... @@ -42,8 +42,6 @@
return nil;
contents = aContents;
path = CGPathCreateMutable();
lineWidth = 100.0f;
drawingMode = kCGPathFillStroke;
... ... @@ -52,6 +50,7 @@
self.masksToBounds = NO;
scaleLineWidth = YES;
boundsInMercators = CGRectZero;
// self.frame = CGRectMake(100, 100, 100, 100);
// [self setNeedsDisplayOnBoundsChange:YES];
... ... @@ -68,6 +67,8 @@
CGPathRelease(path);
[self setLineColor:nil];
[self setFillColor:nil];
[points release];
points = nil;
[super dealloc];
}
... ... @@ -80,26 +81,53 @@
- (void) recalculateGeometry
{
float scale = [[contents mercatorToScreenProjection] scale];
// The bounds are actually in mercators...
CGRect boundsInMercators = CGPathGetBoundingBox(path);
boundsInMercators.origin.x -= lineWidth;
boundsInMercators.origin.y -= lineWidth;
boundsInMercators.size.width += 2*lineWidth;
boundsInMercators.size.height += 2*lineWidth;
CGRect pixelBounds = RMScaleCGRectAboutPoint(boundsInMercators, 1.0f / scale, CGPointMake(0,0));
float scaledLineWidth;
CGPoint myPosition;
CGRect pixelBounds, screenBounds;
float offset;
const float outset = 100.0f; // provides a buffer off screen edges for when path is scaled or moved
// NSLog(@"old bounds: %f %f %f %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height);
self.bounds = pixelBounds;
// NSLog(@"new bounds: %f %f %f %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height);
// NSLog(@"old position: %f %f", self.position.x, self.position.y);
self.position = [[contents mercatorToScreenProjection] projectXYPoint: origin];
// NSLog(@"new position: %f %f", self.position.x, self.position.y);
scaledLineWidth = lineWidth;
if(!scaleLineWidth) {
renderedScale = [contents scale];
scaledLineWidth *= renderedScale;
}
pixelBounds = CGRectInset(boundsInMercators, -scaledLineWidth, -scaledLineWidth);
pixelBounds = RMScaleCGRectAboutPoint(pixelBounds, 1.0f / scale, CGPointZero);
// NSLog(@"Old anchor point %f %f", self.anchorPoint.x, self.anchorPoint.y);
// Clip bound rect to screen bounds.
// If bounds are not clipped, they won't display when you zoom in too much.
myPosition = [[contents mercatorToScreenProjection] projectXYPoint: origin];
screenBounds = [contents screenBounds];
// Clip top
offset = myPosition.y + pixelBounds.origin.y - screenBounds.origin.y + outset;
if(offset < 0.0f) {
pixelBounds.origin.y -= offset;
pixelBounds.size.height += offset;
}
// Clip left
offset = myPosition.x + pixelBounds.origin.x - screenBounds.origin.x + outset;
if(offset < 0.0f) {
pixelBounds.origin.x -= offset;
pixelBounds.size.width += offset;
}
// Clip bottom
offset = myPosition.y + pixelBounds.origin.y + pixelBounds.size.height - screenBounds.origin.y - screenBounds.size.height - outset;
if(offset > 0.0f) {
pixelBounds.size.height -= offset;
}
// Clip right
offset = myPosition.x + pixelBounds.origin.x + pixelBounds.size.width - screenBounds.origin.x - screenBounds.size.width - outset;
if(offset > 0.0f) {
pixelBounds.size.width -= offset;
}
self.position = myPosition;
self.bounds = pixelBounds;
self.anchorPoint = CGPointMake(-pixelBounds.origin.x / pixelBounds.size.width,-pixelBounds.origin.y / pixelBounds.size.height);
// NSLog(@"new anchor point %f %f", self.anchorPoint.x, self.anchorPoint.y);
[self setNeedsDisplay];
}
- (void) addLineToXY: (RMXYPoint) point
... ... @@ -110,12 +138,12 @@
if (points == nil)
{
points = [[NSMutableArray alloc] init];
[points addObject:value];
points = [[NSMutableArray alloc] initWithObjects:value, nil];
origin = point;
self.position = [[contents mercatorToScreenProjection] projectXYPoint: origin];
// NSLog(@"screen position set to %f %f", self.position.x, self.position.y);
path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 0.0f, 0.0f);
}
else
... ... @@ -127,9 +155,11 @@
CGPathAddLineToPoint(path, NULL, point.x, -point.y);
// The bounds are actually in mercators...
boundsInMercators = CGPathGetBoundingBox(path);
[self recalculateGeometry];
}
[self setNeedsDisplay];
}
- (void) addLineToScreenPoint: (CGPoint) point
... ... @@ -148,18 +178,24 @@
- (void)drawInContext:(CGContextRef)theContext
{
renderedScale = [contents scale];
float scale, scaledLineWidth;
// CGContextFillRect(theContext, self.bounds);//CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
float scale = 1.0f / [contents scale];
renderedScale = [contents scale];
scale = 1.0f / renderedScale;
scaledLineWidth = lineWidth;
if(!scaleLineWidth) {
scaledLineWidth *= renderedScale;
}
CGContextScaleCTM(theContext, scale, scale);
CGContextBeginPath(theContext);
CGContextAddPath(theContext, path);
CGContextSetLineWidth(theContext, lineWidth);
CGContextSetLineWidth(theContext, scaledLineWidth);
CGContextSetStrokeColorWithColor(theContext, [lineColor CGColor]);
CGContextSetFillColorWithColor(theContext, [fillColor CGColor]);
CGContextDrawPath(theContext, drawingMode);
... ... @@ -180,7 +216,6 @@
{
lineWidth = newLineWidth;
[self recalculateGeometry];
[self setNeedsDisplay];
}
- (CGPathDrawingMode) drawingMode
... ... @@ -220,16 +255,28 @@
}
}
- (BOOL)scaleLineWidth
{
return scaleLineWidth;
}
- (void)setScaleLineWidth:(BOOL)newState
{
scaleLineWidth = newState;
[self recalculateGeometry];
}
- (void)moveBy: (CGSize) delta {
[super moveBy:delta];
[self recalculateGeometry];
}
- (void)zoomByFactor: (float) zoomFactor near:(CGPoint) pivot
{
[super zoomByFactor:zoomFactor near:pivot];
float newScale = [contents scale];
if (newScale / renderedScale >= 2.0f
|| newScale / renderedScale <= 0.4f)
{
[self setNeedsDisplay];
}
[self recalculateGeometry];
}
@end
... ...