PageRenderTime 56ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/MapView/Map/RMCircle.m

http://github.com/route-me/route-me
Objective C | 184 lines | 114 code | 38 blank | 32 comment | 6 complexity | ef9bed78abe323a96df2bba677805caa MD5 | raw file
  1. ///
  2. // RMCircle.m
  3. //
  4. // Copyright (c) 2008-2010, Route-Me Contributors
  5. // All rights reserved.
  6. //
  7. // Redistribution and use in source and binary forms, with or without
  8. // modification, are permitted provided that the following conditions are met:
  9. //
  10. // * Redistributions of source code must retain the above copyright notice, this
  11. // list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above copyright notice,
  13. // this list of conditions and the following disclaimer in the documentation
  14. // and/or other materials provided with the distribution.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  20. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26. // POSSIBILITY OF SUCH DAMAGE.
  27. #import "RMCircle.h"
  28. #import "RMMapContents.h"
  29. #import "RMProjection.h"
  30. #import "RMMercatorToScreenProjection.h"
  31. #define kDefaultLineWidth 10
  32. #define kDefaultLineColor [UIColor blackColor]
  33. #define kDefaultFillColor [UIColor blueColor]
  34. @interface RMCircle ()
  35. - (void)updateCirclePath;
  36. @end
  37. @implementation RMCircle
  38. @synthesize shapeLayer;
  39. @synthesize projectedLocation;
  40. @synthesize enableDragging;
  41. @synthesize enableRotation;
  42. @synthesize lineColor;
  43. @synthesize fillColor;
  44. @synthesize radiusInMeters;
  45. @synthesize lineWidthInPixels;
  46. - (id)initWithContents:(RMMapContents*)aContents radiusInMeters:(CGFloat)newRadiusInMeters latLong:(RMLatLong)newLatLong {
  47. self = [super init];
  48. if (self) {
  49. CAShapeLayer* newShapeLayer = [[CAShapeLayer alloc] init];
  50. shapeLayer = newShapeLayer;
  51. [self addSublayer:newShapeLayer];
  52. mapContents = aContents;
  53. radiusInMeters = newRadiusInMeters;
  54. latLong = newLatLong;
  55. projectedLocation = [[mapContents projection] latLongToPoint:newLatLong];
  56. [self setPosition:[[mapContents mercatorToScreenProjection] projectXYPoint:projectedLocation]];
  57. // DLog(@"Position: %f, %f", [self position].x, [self position].y);
  58. lineWidthInPixels = kDefaultLineWidth;
  59. lineColor = kDefaultLineColor;
  60. fillColor = kDefaultFillColor;
  61. scaleLineWidth = NO;
  62. enableDragging = YES;
  63. enableRotation = YES;
  64. circlePath = NULL;
  65. [self updateCirclePath];
  66. }
  67. return self;
  68. }
  69. - (void)dealloc {
  70. [shapeLayer release];
  71. shapeLayer = nil;
  72. CGPathRelease(circlePath);
  73. [lineColor release];
  74. lineColor = nil;
  75. [fillColor release];
  76. fillColor = nil;
  77. [super dealloc];
  78. }
  79. #pragma mark -
  80. - (void)updateCirclePath {
  81. CGPathRelease(circlePath);
  82. CGMutablePathRef newPath = CGPathCreateMutable();
  83. CGFloat latRadians = latLong.latitude * M_PI / 180.0f;
  84. CGFloat pixelRadius = radiusInMeters / cos(latRadians) / [mapContents metersPerPixel];
  85. // DLog(@"Pixel Radius: %f", pixelRadius);
  86. CGRect rectangle = CGRectMake(self.position.x - pixelRadius,
  87. self.position.y - pixelRadius,
  88. (pixelRadius * 2),
  89. (pixelRadius * 2));
  90. CGFloat offset = floorf(-lineWidthInPixels / 2.0f) - 2;
  91. // DLog(@"Offset: %f", offset);
  92. CGRect newBoundsRect = CGRectInset(rectangle, offset, offset);
  93. [self setBounds:newBoundsRect];
  94. // DLog(@"Circle Rectangle: %f, %f, %f, %f", rectangle.origin.x, rectangle.origin.y, rectangle.size.width, rectangle.size.height);
  95. // DLog(@"Bounds Rectangle: %f, %f, %f, %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height);
  96. CGPathAddEllipseInRect(newPath, NULL, rectangle);
  97. circlePath = newPath;
  98. [[self shapeLayer] setPath:newPath];
  99. [[self shapeLayer] setFillColor:[fillColor CGColor]];
  100. [[self shapeLayer] setStrokeColor:[lineColor CGColor]];
  101. [[self shapeLayer] setLineWidth:lineWidthInPixels];
  102. }
  103. #pragma mark Accessors
  104. - (void)setProjectedLocation:(RMProjectedPoint)newProjectedLocation {
  105. projectedLocation = newProjectedLocation;
  106. [self setPosition:[[mapContents mercatorToScreenProjection] projectXYPoint:projectedLocation]];
  107. }
  108. - (void)setLineColor:(UIColor*)newLineColor {
  109. if (lineColor != newLineColor) {
  110. [lineColor release];
  111. lineColor = [newLineColor retain];
  112. [self updateCirclePath];
  113. }
  114. }
  115. - (void)setFillColor:(UIColor*)newFillColor {
  116. if (fillColor != newFillColor) {
  117. [fillColor release];
  118. fillColor = [newFillColor retain];
  119. [self updateCirclePath];
  120. }
  121. }
  122. - (void)setRadiusInMeters:(CGFloat)newRadiusInMeters {
  123. radiusInMeters = newRadiusInMeters;
  124. [self updateCirclePath];
  125. }
  126. - (void)setLineWidthInPixels:(CGFloat)newLineWidthInPixels {
  127. lineWidthInPixels = newLineWidthInPixels;
  128. [self updateCirclePath];
  129. }
  130. #pragma mark Map Movement and Scaling
  131. - (void)moveBy:(CGSize)delta {
  132. if (enableDragging) {
  133. [super moveBy:delta];
  134. }
  135. }
  136. - (void)zoomByFactor:(float)zoomFactor near:(CGPoint)center {
  137. [super zoomByFactor:zoomFactor near:center];
  138. [self updateCirclePath];
  139. }
  140. - (void)moveToLatLong:(RMLatLong)newLatLong {
  141. latLong = newLatLong;
  142. [self setProjectedLocation:[[mapContents projection] latLongToPoint:newLatLong]];
  143. [self setPosition:[[mapContents mercatorToScreenProjection] projectXYPoint:projectedLocation]];
  144. // DLog(@"Position: %f, %f", [self position].x, [self position].y);
  145. }
  146. @end