diff options
-rw-r--r-- | Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h | 1 | ||||
-rw-r--r-- | Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m | 298 | ||||
-rw-r--r-- | Source/SPGeometryDataView.h | 16 | ||||
-rw-r--r-- | Source/SPGeometryDataView.m | 114 | ||||
-rw-r--r-- | Source/SPTableContent.m | 10 |
5 files changed, 435 insertions, 4 deletions
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h index 7d141991..cca59b30 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h @@ -58,6 +58,7 @@ typedef struct st_point_2d_ - (NSUInteger)length; - (NSData*)data; - (NSString*)wktString; +- (NSDictionary*)coordinates; - (NSInteger)wkbType; - (NSString*)wktType; diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m index 1c511af3..b46a0dc7 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m @@ -352,6 +352,304 @@ } /** + * Return a dictionary of coordinates, bbox, etc. to be able to draw the given geometry. + * + * @return A dictionary having the following keys: "bbox" as NSArray of NSNumbers of x_min x_max y_min y_max, "coordinates" as NSArray containing the + * the to be drawn points as NSPoint strings, "type" as NSString + */ +- (NSDictionary*)coordinates +{ + + char byteOrder; + UInt32 geoType, numberOfItems, numberOfSubItems, numberOfSubSubItems, numberOfCollectionItems; + st_point_2d aPoint; + + NSUInteger i, j, k, n; // Loop counter for numberOf...Items + NSUInteger ptr = BUFFER_START; // pointer to geoBuffer while parsing + + double x_min = 1e999; + double x_max = -1e999; + double y_min = 1e999; + double y_max = -1e999; + + NSMutableArray *coordinates = [NSMutableArray array]; + NSMutableArray *subcoordinates = [NSMutableArray array]; + + if (bufferLength < WKB_HEADER_SIZE) + return @"Header Error"; + + byteOrder = geoBuffer[ptr]; + + if(byteOrder != 0x1) + return @"Byte order not yet supported"; + + ptr++; + geoType = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32; + + switch(geoType) { + + case wkb_point: + memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + x_min = aPoint.x; + x_max = aPoint.x; + y_min = aPoint.y; + y_max = aPoint.y; + [coordinates addObject:NSStringFromPoint(NSMakePoint(aPoint.x, aPoint.y))]; + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSArray arrayWithObjects: + [NSNumber numberWithDouble:x_min], + [NSNumber numberWithDouble:x_max], + [NSNumber numberWithDouble:y_min], + [NSNumber numberWithDouble:y_max], + nil], @"bbox", + coordinates, @"coordinates", + @"POINT", @"type", + nil]; + break; + + case wkb_linestring: + numberOfItems = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32; + for(i=0; i < numberOfItems; i++) { + memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + x_min = (aPoint.x < x_min) ? aPoint.x : x_min; + x_max = (aPoint.x > x_max) ? aPoint.x : x_max; + y_min = (aPoint.y < y_min) ? aPoint.y : y_min; + y_max = (aPoint.y > y_max) ? aPoint.y : y_max; + [coordinates addObject:NSStringFromPoint(NSMakePoint(aPoint.x, aPoint.y))]; + ptr += POINT_DATA_SIZE; + } + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSArray arrayWithObjects: + [NSNumber numberWithDouble:x_min], + [NSNumber numberWithDouble:x_max], + [NSNumber numberWithDouble:y_min], + [NSNumber numberWithDouble:y_max], + nil], @"bbox", + coordinates, @"coordinates", + @"LINESTRING", @"type", + nil]; + break; + + case wkb_polygon: + numberOfItems = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32; + for(i=0; i < numberOfItems; i++) { + numberOfSubItems = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32; + for(j=0; j < numberOfSubItems; j++) { + memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + x_min = (aPoint.x < x_min) ? aPoint.x : x_min; + x_max = (aPoint.x > x_max) ? aPoint.x : x_max; + y_min = (aPoint.y < y_min) ? aPoint.y : y_min; + y_max = (aPoint.y > y_max) ? aPoint.y : y_max; + [subcoordinates addObject:NSStringFromPoint(NSMakePoint(aPoint.x, aPoint.y))]; + ptr += POINT_DATA_SIZE; + } + [coordinates addObject:[[subcoordinates copy] autorelease]]; + [subcoordinates removeAllObjects]; + } + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSArray arrayWithObjects: + [NSNumber numberWithDouble:x_min], + [NSNumber numberWithDouble:x_max], + [NSNumber numberWithDouble:y_min], + [NSNumber numberWithDouble:y_max], + nil], @"bbox", + coordinates, @"coordinates", + @"POLYGON", @"type", + nil]; + break; + + // case wkb_multipoint: + // [wkt setString:@"MULTIPOINT("]; + // numberOfItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32+WKB_HEADER_SIZE; + // for(i=0; i < numberOfItems; i++) { + // memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + // [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (i < numberOfItems-1) ? @"," : @""]; + // ptr += POINT_DATA_SIZE+WKB_HEADER_SIZE; + // } + // [wkt appendString:@")"]; + // return wkt; + // break; + // + // case wkb_multilinestring: + // [wkt setString:@"MULTILINESTRING("]; + // numberOfItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32+WKB_HEADER_SIZE; + // for(i=0; i < numberOfItems; i++) { + // numberOfSubItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // [wkt appendString:@"("]; + // for(j=0; j < numberOfSubItems; j++) { + // memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + // [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (j < numberOfSubItems-1) ? @"," : @""]; + // ptr += POINT_DATA_SIZE; + // } + // ptr += WKB_HEADER_SIZE; + // [wkt appendFormat:@")%@", (i < numberOfItems-1) ? @"," : @""]; + // } + // [wkt appendString:@")"]; + // return wkt; + // break; + // + // case wkb_multipolygon: + // [wkt setString:@"MULTIPOLYGON("]; + // numberOfItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32+WKB_HEADER_SIZE; + // for(i=0; i < numberOfItems; i++) { + // numberOfSubItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // [wkt appendString:@"("]; + // for(j=0; j < numberOfSubItems; j++) { + // numberOfSubSubItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // [wkt appendString:@"("]; + // for(k=0; k < numberOfSubSubItems; k++) { + // memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + // [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (k < numberOfSubSubItems-1) ? @"," : @""]; + // ptr += POINT_DATA_SIZE; + // } + // [wkt appendFormat:@")%@", (j < numberOfSubItems-1) ? @"," : @""]; + // } + // ptr += WKB_HEADER_SIZE; + // [wkt appendFormat:@")%@", (i < numberOfItems-1) ? @"," : @""]; + // } + // [wkt appendString:@")"]; + // return wkt; + // break; + // + // case wkb_geometrycollection: + // [wkt setString:@"GEOMETRYCOLLECTION("]; + // numberOfCollectionItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // + // for(n=0; n < numberOfCollectionItems; n++) { + // + // byteOrder = geoBuffer[ptr]; + // + // if(byteOrder != 0x1) + // return @"Byte order not yet supported"; + // + // ptr++; + // geoType = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // + // switch(geoType) { + // + // case wkb_point: + // memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + // [wkt appendFormat:@"POINT(%.16g %.16g)", aPoint.x, aPoint.y]; + // ptr += POINT_DATA_SIZE; + // break; + // + // case wkb_linestring: + // [wkt appendString:@"LINESTRING("]; + // numberOfItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // for(i=0; i < numberOfItems; i++) { + // memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + // [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (i < numberOfItems-1) ? @"," : @""]; + // ptr += POINT_DATA_SIZE; + // } + // [wkt appendString:@")"]; + // break; + // + // case wkb_polygon: + // [wkt appendString:@"POLYGON("]; + // numberOfItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // for(i=0; i < numberOfItems; i++) { + // numberOfSubItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // [wkt appendString:@"("]; + // for(j=0; j < numberOfSubItems; j++) { + // memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + // [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (j < numberOfSubItems-1) ? @"," : @""]; + // ptr += POINT_DATA_SIZE; + // } + // [wkt appendFormat:@")%@", (i < numberOfItems-1) ? @"," : @""]; + // } + // [wkt appendString:@")"]; + // break; + // + // case wkb_multipoint: + // [wkt appendString:@"MULTIPOINT("]; + // numberOfItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32+WKB_HEADER_SIZE; + // for(i=0; i < numberOfItems; i++) { + // memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + // [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (i < numberOfItems-1) ? @"," : @""]; + // ptr += POINT_DATA_SIZE+WKB_HEADER_SIZE; + // } + // ptr -= WKB_HEADER_SIZE; + // [wkt appendString:@")"]; + // break; + // + // case wkb_multilinestring: + // [wkt appendString:@"MULTILINESTRING("]; + // numberOfItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32+WKB_HEADER_SIZE; + // for(i=0; i < numberOfItems; i++) { + // numberOfSubItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // [wkt appendString:@"("]; + // for(j=0; j < numberOfSubItems; j++) { + // memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + // [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (j < numberOfSubItems-1) ? @"," : @""]; + // ptr += POINT_DATA_SIZE; + // } + // ptr += WKB_HEADER_SIZE; + // [wkt appendFormat:@")%@", (i < numberOfItems-1) ? @"," : @""]; + // } + // ptr -= WKB_HEADER_SIZE; + // [wkt appendString:@")"]; + // break; + // + // case wkb_multipolygon: + // [wkt appendString:@"MULTIPOLYGON("]; + // numberOfItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32+WKB_HEADER_SIZE; + // for(i=0; i < numberOfItems; i++) { + // numberOfSubItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // [wkt appendString:@"("]; + // for(j=0; j < numberOfSubItems; j++) { + // numberOfSubSubItems = geoBuffer[ptr]; + // ptr += SIZEOF_STORED_UINT32; + // [wkt appendString:@"("]; + // for(k=0; k < numberOfSubSubItems; k++) { + // memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + // [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (k < numberOfSubSubItems-1) ? @"," : @""]; + // ptr += POINT_DATA_SIZE; + // } + // [wkt appendFormat:@")%@", (j < numberOfSubItems-1) ? @"," : @""]; + // } + // ptr += WKB_HEADER_SIZE; + // [wkt appendFormat:@")%@", (i < numberOfItems-1) ? @"," : @""]; + // } + // ptr -= WKB_HEADER_SIZE; + // [wkt appendString:@")"]; + // break; + // + // default: + // return @"Error geometrycollection type parsing"; + // } + // [wkt appendString:(n < numberOfCollectionItems-1) ? @"," : @""]; + // } + // [wkt appendString:@")"]; + // return wkt; + break; + + default: + return nil; + } + return nil; +} + +/** * Return the WKB type of the geoBuffer ie if buffer represents a POINT, LINESTRING, etc. * according to stored wkbType in header file. It returns -1 if an error occurred. */ diff --git a/Source/SPGeometryDataView.h b/Source/SPGeometryDataView.h index a2a620bb..3ff72110 100644 --- a/Source/SPGeometryDataView.h +++ b/Source/SPGeometryDataView.h @@ -27,7 +27,21 @@ @interface SPGeometryDataView : NSView { - + NSString *type; + NSArray *coordinates; + double x_min; + double x_max; + double y_min; + double y_max; + double width; + double height; + double zoom_factor; + double margin_offset; } +- (id)initWithCoordinates:(NSDictionary*)coord; +- (void)setMax:(NSArray*)bbox; +- (NSPoint)normalizePoint:(NSPoint)aPoint; +- (NSImage*)image; + @end diff --git a/Source/SPGeometryDataView.m b/Source/SPGeometryDataView.m index 8cfaf767..45d9632b 100644 --- a/Source/SPGeometryDataView.m +++ b/Source/SPGeometryDataView.m @@ -30,15 +30,125 @@ /** * Initialize SPGeometryDataView object */ -- (id)initWithFrame:(NSRect)frame +- (id)initWithCoordinates:(NSDictionary*)coord { - if ( self = [super initWithFrame:frame] ) + + margin_offset = 5.0; + + type = [coord objectForKey:@"type"]; + coordinates = [coord objectForKey:@"coordinates"]; + x_min = [[[coord objectForKey:@"bbox"] objectAtIndex:0] doubleValue] - margin_offset; + x_max = [[[coord objectForKey:@"bbox"] objectAtIndex:1] doubleValue] + margin_offset; + y_min = [[[coord objectForKey:@"bbox"] objectAtIndex:2] doubleValue] - margin_offset; + y_max = [[[coord objectForKey:@"bbox"] objectAtIndex:3] doubleValue] + margin_offset; + + zoom_factor = 1.0; + + width = x_max - x_min; + height = y_max - y_min; + + + if ( self = [super initWithFrame:NSMakeRect(0,0,width,height)] ) { ; } return self; } +- (NSPoint)normalizePoint:(NSPoint)aPoint +{ + return aPoint; +} + +- (void)drawRect:(NSRect)dirtyRect +{ + + if(!type || ![type length] || !coordinates || ![coordinates count]) return; + + NSBezierPath *path, *circlePath; + NSColor *polyFillColor = [NSColor colorWithCalibratedRed:.5 green:.5 blue:0.5 alpha:0.05]; + BOOL isFirst = YES; + + NSPoint aPoint; + + path = [NSBezierPath bezierPathWithRect:[self bounds]]; + [path setLineWidth:0.1]; + [[NSColor whiteColor] set]; + [path fill]; + [[NSColor grayColor] set]; + [path stroke]; + + path = [NSBezierPath bezierPath]; + [[NSColor blackColor] set]; + [path setLineWidth:1]; + + if ([type isEqualToString:@"POINT"]) { + circlePath = [NSBezierPath bezierPath]; + [circlePath appendBezierPathWithOvalInRect:NSMakeRect(width/2-2,height/2-2,4,4)]; + [[NSColor grayColor] setStroke]; + [[NSColor redColor] setFill]; + [circlePath stroke]; + [circlePath fill]; + } + else if([type isEqualToString:@"LINESTRING"]) { + + for(NSString* coord in coordinates) { + aPoint = [self normalizePoint:NSPointFromString(coord)]; + if(isFirst) { + [path moveToPoint:aPoint]; + isFirst = NO; + } else { + [path lineToPoint:aPoint]; + } + circlePath = [NSBezierPath bezierPath]; + [circlePath appendBezierPathWithOvalInRect:NSMakeRect(aPoint.x-2,aPoint.y-2,4,4)]; + [[NSColor grayColor] setStroke]; + [[NSColor redColor] setFill]; + [circlePath stroke]; + [circlePath fill]; + } + [[NSColor blackColor] setStroke]; + [path stroke]; + + } + else if([type isEqualToString:@"POLYGON"]) { + for(NSArray* polygon in coordinates) { + isFirst = YES; + for(NSString* coord in polygon) { + aPoint = [self normalizePoint:NSPointFromString(coord)]; + if(isFirst) { + [path moveToPoint:aPoint]; + isFirst = NO; + } else { + [path lineToPoint:aPoint]; + } + circlePath = [NSBezierPath bezierPath]; + [circlePath appendBezierPathWithOvalInRect:NSMakeRect(aPoint.x-2,aPoint.y-2,4,4)]; + [[NSColor grayColor] setStroke]; + [[NSColor redColor] setFill]; + [circlePath stroke]; + [circlePath fill]; + } + [[NSColor blackColor] setStroke]; + [polyFillColor setFill]; + [path fill]; + [path stroke]; + } + + } +} + +- (NSImage*)image +{ + + [self drawRect:[self bounds]]; + + NSImage *image = [[[NSImage alloc] initWithSize:[self bounds].size] autorelease]; + NSBitmapImageRep *bitmap = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:[self bounds]] autorelease]; + [image addRepresentation:bitmap]; + return image; +} + /** * dealloc */ diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m index 50ce0617..3aa154a7 100644 --- a/Source/SPTableContent.m +++ b/Source/SPTableContent.m @@ -51,6 +51,7 @@ #import "SPAlertSheets.h" #import "SPMainThreadTrampoline.h" #import "SPHistoryController.h" +#import "SPGeometryDataView.h" @implementation SPTableContent @@ -3349,7 +3350,14 @@ } } else if ([theValue isKindOfClass:[MCPGeometryData class]]) { - ; // TODO + // SPGeometryDataView *v = [[SPGeometryDataView alloc] initWithCoordinates:[theValue coordinates]]; + // image = [v image]; + // if(image) { + // [SPTooltip showWithObject:image atLocation:pos ofType:@"image"]; + // [v release]; + // return nil; + // } + // [v release]; } // Show the cell string value as tooltip (including line breaks and tabs) |