Authored by Vladimir Vyskocil

Merge of the Luca's patch modified by Ivo Brodien from the route-me mailling-lis…

…t. Fix problems with path overlay layer diseappearing (size > 1024 pixels)
@@ -130,23 +130,26 @@ @@ -130,23 +130,26 @@
130 - (CGPoint) projectXYPoint:(RMProjectedPoint)aPoint withMetersPerPixel:(float)aScale 130 - (CGPoint) projectXYPoint:(RMProjectedPoint)aPoint withMetersPerPixel:(float)aScale
131 { 131 {
132 CGPoint aPixelPoint; 132 CGPoint aPixelPoint;
133 - CGFloat originX = origin.easting;  
134 - CGFloat boundsWidth = [projection planetBounds].size.width;  
135 - CGFloat pointX = aPoint.easting - boundsWidth/2;  
136 - CGFloat left = sqrt((pointX - (originX - boundsWidth))*(pointX - (originX - boundsWidth)));  
137 - CGFloat middle = sqrt((pointX - originX)*(pointX - originX));  
138 - CGFloat right = sqrt((pointX - (originX + boundsWidth))*(pointX - (originX + boundsWidth)));  
139 -  
140 - if(middle <= left && middle <= right){  
141 - aPixelPoint.x = (aPoint.easting - originX) / aScale;  
142 - } else if(left <= middle && left <= right){  
143 - aPixelPoint.x = (aPoint.easting - (originX-boundsWidth)) / aScale;  
144 - } else{ //right  
145 - aPixelPoint.x = (aPoint.easting - (originX+boundsWidth)) / aScale;  
146 - } 133 + CGFloat originX = origin.easting;
  134 + CGFloat boundsWidth = [projection planetBounds].size.width;
  135 + CGFloat pointX = aPoint.easting - boundsWidth/2;
  136 + CGFloat left = sqrt((pointX - (originX - boundsWidth))*(pointX - (originX - boundsWidth)));
  137 + CGFloat middle = sqrt((pointX - originX)*(pointX - originX));
  138 + CGFloat right = sqrt((pointX - (originX + boundsWidth))*(pointX - (originX + boundsWidth)));
  139 +
  140 + //RMLog(@"left:%f middle:%f right:%f x:%f width:%f", left, middle, right, pointX, boundsWidth);//LK
  141 +
  142 + if(middle <= left && middle <= right){
  143 + aPixelPoint.x = (aPoint.easting - originX) / aScale;
  144 + } else if(left <= middle && left <= right){
  145 + //RMLog(@"warning: projectXYPoint middle..");//LK
  146 + aPixelPoint.x = (aPoint.easting - (originX/*-boundsWidth*/)) / aScale;
  147 + } else{ //right
  148 + aPixelPoint.x = (aPoint.easting - (originX+boundsWidth)) / aScale;
  149 + }
147 150
148 aPixelPoint.y = screenBounds.size.height - (aPoint.northing - origin.northing) / aScale; 151 aPixelPoint.y = screenBounds.size.height - (aPoint.northing - origin.northing) / aScale;
149 - return aPixelPoint; 152 + return aPixelPoint;
150 } 153 }
151 154
152 - (CGPoint) projectXYPoint: (RMProjectedPoint)aPoint 155 - (CGPoint) projectXYPoint: (RMProjectedPoint)aPoint
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 // POSSIBILITY OF SUCH DAMAGE. 26 // POSSIBILITY OF SUCH DAMAGE.
27 -#import "RMGlobalConstants.h" 27 +
28 #import "RMPath.h" 28 #import "RMPath.h"
29 #import "RMMapView.h" 29 #import "RMMapView.h"
30 #import "RMMapContents.h" 30 #import "RMMapContents.h"
@@ -52,11 +52,11 @@ @@ -52,11 +52,11 @@
52 drawingMode = kCGPathFillStroke; 52 drawingMode = kCGPathFillStroke;
53 lineColor = [UIColor blackColor]; 53 lineColor = [UIColor blackColor];
54 fillColor = [UIColor redColor]; 54 fillColor = [UIColor redColor];
55 - self.masksToBounds = NO;  
56 55
57 - scaleLineWidth = YES;  
58 -// self.frame = CGRectMake(100, 100, 100, 100);  
59 -// [self setNeedsDisplayOnBoundsChange:YES]; 56 + //self.masksToBounds = NO;
  57 + self.masksToBounds = YES;
  58 +
  59 + scaleLineWidth = NO;
60 60
61 return self; 61 return self;
62 } 62 }
@@ -81,42 +81,74 @@ @@ -81,42 +81,74 @@
81 } 81 }
82 82
83 - (void) recalculateGeometry 83 - (void) recalculateGeometry
84 -{ 84 +{
85 float scale = [[contents mercatorToScreenProjection] metersPerPixel]; 85 float scale = [[contents mercatorToScreenProjection] metersPerPixel];
  86 + float scaledLineWidth;
  87 + CGPoint myPosition;
  88 + CGRect pixelBounds, screenBounds;
  89 + float offset;
  90 + const float outset = 100.0f; // provides a buffer off screen edges for when path is scaled or moved
86 91
87 - float scaledLineWidth = lineWidth; 92 +
  93 + // The bounds are actually in mercators...
  94 + /// \bug if "bounds are actually in mercators", shouldn't be using a CGRect
  95 + scaledLineWidth = lineWidth;
88 if(!scaleLineWidth) { 96 if(!scaleLineWidth) {
89 renderedScale = [contents metersPerPixel]; 97 renderedScale = [contents metersPerPixel];
90 scaledLineWidth *= renderedScale; 98 scaledLineWidth *= renderedScale;
91 } 99 }
92 100
93 - // The bounds are actually in mercators...  
94 - /// \bug if "bounds are actually in mercators", shouldn't be using a CGRect  
95 CGRect boundsInMercators = CGPathGetBoundingBox(path); 101 CGRect boundsInMercators = CGPathGetBoundingBox(path);
96 boundsInMercators.origin.x -= scaledLineWidth; 102 boundsInMercators.origin.x -= scaledLineWidth;
97 boundsInMercators.origin.y -= scaledLineWidth; 103 boundsInMercators.origin.y -= scaledLineWidth;
98 boundsInMercators.size.width += 2*scaledLineWidth; 104 boundsInMercators.size.width += 2*scaledLineWidth;
99 boundsInMercators.size.height += 2*scaledLineWidth; 105 boundsInMercators.size.height += 2*scaledLineWidth;
100 106
101 - CGRect pixelBounds = RMScaleCGRectAboutPoint(boundsInMercators, 1.0f / scale, CGPointZero);  
102 -  
103 -// RMLog(@"old bounds: %f %f %f %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height); 107 + pixelBounds = CGRectInset(boundsInMercators, -scaledLineWidth, -scaledLineWidth);
  108 +
  109 + pixelBounds = RMScaleCGRectAboutPoint(pixelBounds, 1.0f / scale, CGPointZero);
  110 +
  111 + // Clip bound rect to screen bounds.
  112 + // If bounds are not clipped, they won't display when you zoom in too much.
  113 + myPosition = [[contents mercatorToScreenProjection] projectXYPoint: origin];
  114 + screenBounds = [contents screenBounds];
  115 +
  116 + // Clip top
  117 + offset = myPosition.y + pixelBounds.origin.y - screenBounds.origin.y + outset;
  118 + if(offset < 0.0f) {
  119 + pixelBounds.origin.y -= offset;
  120 + pixelBounds.size.height += offset;
  121 + }
  122 + // Clip left
  123 + offset = myPosition.x + pixelBounds.origin.x - screenBounds.origin.x + outset;
  124 + if(offset < 0.0f) {
  125 + pixelBounds.origin.x -= offset;
  126 + pixelBounds.size.width += offset;
  127 + }
  128 + // Clip bottom
  129 + offset = myPosition.y + pixelBounds.origin.y + pixelBounds.size.height - screenBounds.origin.y - screenBounds.size.height - outset;
  130 + if(offset > 0.0f) {
  131 + pixelBounds.size.height -= offset;
  132 + }
  133 + // Clip right
  134 + offset = myPosition.x + pixelBounds.origin.x + pixelBounds.size.width - screenBounds.origin.x - screenBounds.size.width - outset;
  135 + if(offset > 0.0f) {
  136 + pixelBounds.size.width -= offset;
  137 + }
  138 +
  139 + self.position = myPosition;
104 self.bounds = pixelBounds; 140 self.bounds = pixelBounds;
105 -// RMLog(@"new bounds: %f %f %f %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height); 141 + //RMLog(@"x:%f y:%f screen bounds: %f %f %f %f", myPosition.x, myPosition.y, screenBounds.origin.x, screenBounds.origin.y, screenBounds.size.width, screenBounds.size.height);
  142 + //RMLog(@"new bounds: %f %f %f %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height);
106 143
107 -// RMLog(@"old position: %f %f", self.position.x, self.position.y);  
108 - self.position = [[contents mercatorToScreenProjection] projectXYPoint: origin];  
109 -// RMLog(@"new position: %f %f", self.position.x, self.position.y);  
110 -  
111 -// RMLog(@"Old anchor point %f %f", self.anchorPoint.x, self.anchorPoint.y);  
112 self.anchorPoint = CGPointMake(-pixelBounds.origin.x / pixelBounds.size.width,-pixelBounds.origin.y / pixelBounds.size.height); 144 self.anchorPoint = CGPointMake(-pixelBounds.origin.x / pixelBounds.size.width,-pixelBounds.origin.y / pixelBounds.size.height);
113 -// RMLog(@"new anchor point %f %f", self.anchorPoint.x, self.anchorPoint.y); 145 + [self setNeedsDisplay];
114 } 146 }
115 147
116 - (void) addPointToXY: (RMProjectedPoint) point withDrawing: (BOOL)isDrawing 148 - (void) addPointToXY: (RMProjectedPoint) point withDrawing: (BOOL)isDrawing
117 { 149 {
118 -// RMLog(@"addLineToXY %f %f", point.easting, point.northing);  
119 - 150 + // RMLog(@"addLineToXY %f %f", point.x, point.y);
  151 +
120 NSValue* value = [NSValue value:&point withObjCType:@encode(RMProjectedPoint)]; 152 NSValue* value = [NSValue value:&point withObjCType:@encode(RMProjectedPoint)];
121 153
122 if (points == nil) 154 if (points == nil)
@@ -124,24 +156,25 @@ @@ -124,24 +156,25 @@
124 points = [[NSMutableArray alloc] init]; 156 points = [[NSMutableArray alloc] init];
125 [points addObject:value]; 157 [points addObject:value];
126 origin = point; 158 origin = point;
127 - 159 +
128 self.position = [[contents mercatorToScreenProjection] projectXYPoint: origin]; 160 self.position = [[contents mercatorToScreenProjection] projectXYPoint: origin];
129 -// RMLog(@"screen position set to %f %f", self.position.x, self.position.y); 161 + // RMLog(@"screen position set to %f %f", self.position.x, self.position.y);
130 CGPathMoveToPoint(path, NULL, 0.0f, 0.0f); 162 CGPathMoveToPoint(path, NULL, 0.0f, 0.0f);
131 } 163 }
132 else 164 else
133 { 165 {
134 [points addObject:value]; 166 [points addObject:value];
135 - 167 +
136 point.easting = point.easting - origin.easting; 168 point.easting = point.easting - origin.easting;
137 point.northing = point.northing - origin.northing; 169 point.northing = point.northing - origin.northing;
138 - 170 +
139 if (isDrawing) 171 if (isDrawing)
140 { 172 {
141 CGPathAddLineToPoint(path, NULL, point.easting, -point.northing); 173 CGPathAddLineToPoint(path, NULL, point.easting, -point.northing);
142 } else { 174 } else {
143 CGPathMoveToPoint(path, NULL, point.easting, -point.northing); 175 CGPathMoveToPoint(path, NULL, point.easting, -point.northing);
144 } 176 }
  177 +
145 [self recalculateGeometry]; 178 [self recalculateGeometry];
146 } 179 }
147 [self setNeedsDisplay]; 180 [self setNeedsDisplay];
@@ -195,11 +228,12 @@ @@ -195,11 +228,12 @@
195 if(!scaleLineWidth) { 228 if(!scaleLineWidth) {
196 scaledLineWidth *= renderedScale; 229 scaledLineWidth *= renderedScale;
197 } 230 }
  231 + //NSLog(@"line width = %f, content scale = %f", scaledLineWidth, renderedScale);
198 232
199 CGContextScaleCTM(theContext, scale, scale); 233 CGContextScaleCTM(theContext, scale, scale);
200 234
201 CGContextBeginPath(theContext); 235 CGContextBeginPath(theContext);
202 - CGContextAddPath(theContext, path); 236 + CGContextAddPath(theContext, path);
203 237
204 CGContextSetLineWidth(theContext, scaledLineWidth); 238 CGContextSetLineWidth(theContext, scaledLineWidth);
205 CGContextSetStrokeColorWithColor(theContext, [lineColor CGColor]); 239 CGContextSetStrokeColorWithColor(theContext, [lineColor CGColor]);
@@ -254,7 +288,6 @@ @@ -254,7 +288,6 @@
254 { 288 {
255 return fillColor; 289 return fillColor;
256 } 290 }
257 -  
258 - (void)setFillColor:(UIColor *)aFillColor 291 - (void)setFillColor:(UIColor *)aFillColor
259 { 292 {
260 if (fillColor != aFillColor) { 293 if (fillColor != aFillColor) {
@@ -264,18 +297,23 @@ @@ -264,18 +297,23 @@
264 } 297 }
265 } 298 }
266 299
  300 +- (void)moveBy: (CGSize) delta {
  301 + [super moveBy:delta];
  302 +
  303 + [self recalculateGeometry];
  304 +}
  305 +
267 - (void)zoomByFactor: (float) zoomFactor near:(CGPoint) pivot 306 - (void)zoomByFactor: (float) zoomFactor near:(CGPoint) pivot
268 { 307 {
269 [super zoomByFactor:zoomFactor near:pivot]; 308 [super zoomByFactor:zoomFactor near:pivot];
270 -  
271 // don't redraw if the path hasn't been scaled very much 309 // don't redraw if the path hasn't been scaled very much
272 - float newMPP = [contents metersPerPixel];  
273 - if (newMPP / renderedScale >= 2.0f  
274 - || newMPP / renderedScale <= 0.5f) 310 + float newScale = [contents metersPerPixel];
  311 + if (newScale / renderedScale >= 1.10f
  312 + || newScale / renderedScale <= 0.90f)
275 { 313 {
  314 + [self recalculateGeometry];
276 [self setNeedsDisplay]; 315 [self setNeedsDisplay];
277 } 316 }
278 } 317 }
279 318
280 -  
281 @end 319 @end