/MapView/Map/RMCircle.m
Objective C | 184 lines | 114 code | 38 blank | 32 comment | 6 complexity | ef9bed78abe323a96df2bba677805caa MD5 | raw file
- ///
- // RMCircle.m
- //
- // Copyright (c) 2008-2010, Route-Me Contributors
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are met:
- //
- // * Redistributions of source code must retain the above copyright notice, this
- // list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- // POSSIBILITY OF SUCH DAMAGE.
- #import "RMCircle.h"
- #import "RMMapContents.h"
- #import "RMProjection.h"
- #import "RMMercatorToScreenProjection.h"
- #define kDefaultLineWidth 10
- #define kDefaultLineColor [UIColor blackColor]
- #define kDefaultFillColor [UIColor blueColor]
- @interface RMCircle ()
- - (void)updateCirclePath;
- @end
- @implementation RMCircle
- @synthesize shapeLayer;
- @synthesize projectedLocation;
- @synthesize enableDragging;
- @synthesize enableRotation;
- @synthesize lineColor;
- @synthesize fillColor;
- @synthesize radiusInMeters;
- @synthesize lineWidthInPixels;
- - (id)initWithContents:(RMMapContents*)aContents radiusInMeters:(CGFloat)newRadiusInMeters latLong:(RMLatLong)newLatLong {
- self = [super init];
-
- if (self) {
- CAShapeLayer* newShapeLayer = [[CAShapeLayer alloc] init];
- shapeLayer = newShapeLayer;
- [self addSublayer:newShapeLayer];
-
- mapContents = aContents;
- radiusInMeters = newRadiusInMeters;
- latLong = newLatLong;
- projectedLocation = [[mapContents projection] latLongToPoint:newLatLong];
- [self setPosition:[[mapContents mercatorToScreenProjection] projectXYPoint:projectedLocation]];
- // DLog(@"Position: %f, %f", [self position].x, [self position].y);
-
- lineWidthInPixels = kDefaultLineWidth;
- lineColor = kDefaultLineColor;
- fillColor = kDefaultFillColor;
-
- scaleLineWidth = NO;
- enableDragging = YES;
- enableRotation = YES;
-
- circlePath = NULL;
- [self updateCirclePath];
- }
-
- return self;
- }
- - (void)dealloc {
- [shapeLayer release];
- shapeLayer = nil;
- CGPathRelease(circlePath);
- [lineColor release];
- lineColor = nil;
- [fillColor release];
- fillColor = nil;
- [super dealloc];
- }
- #pragma mark -
- - (void)updateCirclePath {
- CGPathRelease(circlePath);
-
- CGMutablePathRef newPath = CGPathCreateMutable();
-
- CGFloat latRadians = latLong.latitude * M_PI / 180.0f;
- CGFloat pixelRadius = radiusInMeters / cos(latRadians) / [mapContents metersPerPixel];
- // DLog(@"Pixel Radius: %f", pixelRadius);
-
- CGRect rectangle = CGRectMake(self.position.x - pixelRadius,
- self.position.y - pixelRadius,
- (pixelRadius * 2),
- (pixelRadius * 2));
-
- CGFloat offset = floorf(-lineWidthInPixels / 2.0f) - 2;
- // DLog(@"Offset: %f", offset);
- CGRect newBoundsRect = CGRectInset(rectangle, offset, offset);
- [self setBounds:newBoundsRect];
-
- // DLog(@"Circle Rectangle: %f, %f, %f, %f", rectangle.origin.x, rectangle.origin.y, rectangle.size.width, rectangle.size.height);
- // DLog(@"Bounds Rectangle: %f, %f, %f, %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height);
-
- CGPathAddEllipseInRect(newPath, NULL, rectangle);
- circlePath = newPath;
-
- [[self shapeLayer] setPath:newPath];
- [[self shapeLayer] setFillColor:[fillColor CGColor]];
- [[self shapeLayer] setStrokeColor:[lineColor CGColor]];
- [[self shapeLayer] setLineWidth:lineWidthInPixels];
- }
- #pragma mark Accessors
- - (void)setProjectedLocation:(RMProjectedPoint)newProjectedLocation {
- projectedLocation = newProjectedLocation;
-
- [self setPosition:[[mapContents mercatorToScreenProjection] projectXYPoint:projectedLocation]];
- }
- - (void)setLineColor:(UIColor*)newLineColor {
- if (lineColor != newLineColor) {
- [lineColor release];
- lineColor = [newLineColor retain];
- [self updateCirclePath];
- }
- }
- - (void)setFillColor:(UIColor*)newFillColor {
- if (fillColor != newFillColor) {
- [fillColor release];
- fillColor = [newFillColor retain];
- [self updateCirclePath];
- }
- }
- - (void)setRadiusInMeters:(CGFloat)newRadiusInMeters {
- radiusInMeters = newRadiusInMeters;
- [self updateCirclePath];
- }
- - (void)setLineWidthInPixels:(CGFloat)newLineWidthInPixels {
- lineWidthInPixels = newLineWidthInPixels;
- [self updateCirclePath];
- }
- #pragma mark Map Movement and Scaling
- - (void)moveBy:(CGSize)delta {
- if (enableDragging) {
- [super moveBy:delta];
- }
- }
- - (void)zoomByFactor:(float)zoomFactor near:(CGPoint)center {
- [super zoomByFactor:zoomFactor near:center];
-
- [self updateCirclePath];
- }
- - (void)moveToLatLong:(RMLatLong)newLatLong {
- latLong = newLatLong;
- [self setProjectedLocation:[[mapContents projection] latLongToPoint:newLatLong]];
- [self setPosition:[[mapContents mercatorToScreenProjection] projectXYPoint:projectedLocation]];
- // DLog(@"Position: %f, %f", [self position].x, [self position].y);
- }
- @end