[Drawkit] Converting units

Graham Cox graham.cox at bigpond.com
Wed May 21 19:38:50 PDT 2008


On 22 May 2008, at 12:11 pm, Brad Larson wrote:

> I'm still working on the file import and am able to programmatically  
> add paths and shapes now, but I'm not able to define shapes in terms  
> of the proper units.  First, I initialize the drawing document with
>
> DKDrawing *currentDrawing = [[DKDrawing alloc]  
> initWithSize:NSMakeSize(1000, 1000)];
> [currentDrawing setDrawingUnits:@"Microns"  
> unitToPointsConversionFactor:(kGCGridDrawingLayerMetricInterval /  
> 10000)];
>
> DKObjectDrawingLayer* currentLayer = [[DKObjectDrawingLayer alloc]  
> init];
> [currentDrawing addLayer:currentLayer];
> [currentDrawing setActiveLayer:currentLayer];
>
> DKGuideLayer* guides = [[DKGuideLayer alloc] init];
> [currentDrawing addLayer:guides];
> [guides release];
>
> I'm starting with our application-specific XML format for our  
> dispenser, which specifies everything in terms of microns (1 cm =  
> 10000 microns), so I set the drawing units to that.  I then set up  
> the layers that I saw were initialized for a blank document in  
> DrawDemo.
>
> I parse the XML document being loaded, and, as an example, for  
> adding a drawn line to the drawing I do the following (code is not  
> efficient, due to debugging):
>
> NSBezierPath* currentBezierPath = [NSBezierPath bezierPath];
> NSPoint pointToConvert = NSMakePoint([[xmlPatternItemAttributes  
> valueForKey:@"x"] doubleValue], [[xmlPatternItemAttributes  
> valueForKey:@"y"] doubleValue]);
> NSLog(@"Before: (%f,%f)",pointToConvert.x, pointToConvert.y);
> DKGridLayer *testLayer = [currentDrawing gridLayer];
> NSPoint convertedPoint = [testLayer  
> pointForGridLocation:pointToConvert];
> NSLog(@"After: (%f,%f)",pointToConvert.x, pointToConvert.y);
> [currentBezierPath moveToPoint:convertedPoint];
>
> pointToConvert = NSMakePoint([[xmlPatternItemAttributes  
> valueForKey:@"x2"] doubleValue], [[xmlPatternItemAttributes  
> valueForKey:@"y2"] doubleValue]);
> NSLog(@"Before: (%f,%f)",pointToConvert.x, pointToConvert.y);
> convertedPoint = [testLayer pointForGridLocation:pointToConvert];
> NSLog(@"After: (%f,%f)",pointToConvert.x, pointToConvert.y);
> [currentBezierPath lineToPoint:[[currentDrawing gridLayer]  
> pointForGridLocation:pointToConvert]];
> 					
> DKDrawablePath* currentPath = [[DKDrawablePath alloc]  
> initWithBezierPath:currentBezierPath];
> [currentPath setPathEditingMode:kGCPathCreateModeLineCreate];	
> [currentLayer addObject:currentPath];
> [currentPath release];
>
> xmlPatternAttributes is an NSDictionary containing the parsed  
> attributes of an imported drawing object, such as the starting x and  
> y coordinates ("x" and "y") and ending x and y coordinates ("x2",  
> "y2") of a line.  It looked to me like DKGridLayer was the  
> repository of methods that would convert from realspace coordinates  
> (x and y in microns) to Quartz coordinates (what's needed for the  
> NSBezierPath) and back.  First, am I right in doing it this way or  
> is there an easier way to create objects starting from realspace  
> coordinates?  Second, [currentDrawing gridLayer] is returning nil.   
> Is there something in the initialization that I've missed?  I think  
> I have everything that the DrawDemo application used for  
> initializing the drawing.


If your code is exactly as above, what you've missed is creating and  
adding the grid layer. I see a guide layer, but no grid layer.
After adding the grid layer, call its -synchronizeRulers method to get  
it to take up the drawing units and conversion factor you set.

Otherwise I think what you're doing should work. If you have a lot of  
objects to read in though I'd probably look at not calling the grid  
layer for every one, but applying the necessary conversion factor  
directly - it will be a lot faster.

>> [currentPath setPathEditingMode:kGCPathCreateModeLineCreate];	

	
I wouldn't bother doing this, as you're not creating the lines  
interactively, which is all this is there to support. You might also  
find it prevents proper editing of the object later. Just leave it set  
to the default value (i.e. don't set it).


cheers, Graham



More information about the Drawkit mailing list