1/* DXFImportSub.m 2 * Subclass of DXFImport managing the creation of graphic objects 3 * 4 * Copyright (C) 1996-2011 by vhf interservice GmbH 5 * Author: Georg Fleischmann 6 * 7 * created: 1996-05-01 8 * modified: 2011-04-04 (-addLine3D:... added) 9 * 2007-07-13 (-setBounds: continue nur wenn object removed wird (Versatz)) 10 * 11 * This file is part of the vhf Import Library. 12 * 13 * This library is free software; you can redistribute it and/or 14 * modify it under the terms of the vhf Public License as 15 * published by the vhf interservice GmbH. Among other things, 16 * the License requires that the copyright notices and this notice 17 * be preserved on all copies. 18 * 19 * This library is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 22 * See the vhf Public License for more details. 23 * 24 * You should have received a copy of the vhf Public License along 25 * with this library; see the file LICENSE. If not, write to vhf. 26 * 27 * If you want to link this library to your proprietary software, 28 * or for other uses which are not covered by the definitions 29 * laid down in the vhf Public License, vhf also offers a proprietary 30 * license scheme. See the vhf internet pages or ask for details. 31 * 32 * vhf interservice GmbH, Im Marxle 3, 72119 Altingen, Germany 33 * eMail: info@vhf.de 34 * http://www.vhf.de 35 */ 36 37#include <ctype.h> 38#include <VHFShared/vhfCommonFunctions.h> 39#include <VHFShared/types.h> 40#include "DXFImportSub.h" 41#include "messages.h" 42#include "Graphics.h" 43#include "LayerObject.h" 44 45@implementation DXFImportSub 46 47/* here we create the layers needed to store the imported graphics 48 * we return an autoreleased object 49 */ 50- (id)allocateList:(NSArray*)layers 51{ int l; 52 53 layerList = [[NSMutableArray alloc] init]; 54 55 /* create a layerList containing a layerObject for each layer */ 56 for (l=0; l<(int)[layers count]; l++) 57 { LayerObject *layerObject = [LayerObject layerObject]; 58 NSDictionary *dict = [layers objectAtIndex:l]; 59 60 [layerObject setString:[dict objectForKey:@"name"]]; 61 //if (!([layerInfo intForKey:@"flags"] & LAYERFLAG_FROZEN)) 62 // ... 63 [layerList addObject:layerObject]; 64 } 65 if (![layers count]) 66 { LayerObject *layerObject = [LayerObject layerObject]; 67 68 [layerObject setString:@"DXF"]; 69 [layerList addObject:layerObject]; 70 } 71 72 return layerList; 73} 74- (NSMutableArray*)layerArrayWithName:(NSString*)name 75{ int l; 76 77 /* AC2.10 seems to allow missing LAYER entries */ 78 if (!name && [layerList count]) 79 return [[layerList objectAtIndex:0] list]; 80 81 for (l=0; l<(int)[layerList count]; l++) 82 if ([[[layerList objectAtIndex:l] string] isEqual:name]) 83 return [[layerList objectAtIndex:l] list]; 84 if ([layerList count]) // return first layer (default) 85 return [[layerList objectAtIndex:0] list]; 86 return nil; 87} 88 89/* add list as filled path to layer 90 * we simply add everything in a single list ignoring all layers 91 */ 92- (void)addFillList:aList toLayer:(NSString*)layerName 93{ NSMutableArray *array = [self layerArrayWithName:layerName]; 94 VPath *g = [VPath path]; 95 96 if (!array) 97 array = [[layerList objectAtIndex:0] list]; 98 [g addList:aList at:[[g list] count]]; 99 [g sortList]; 100 [g setFilled:YES]; 101 [g setWidth:state.width]; 102 [g setColor:state.color]; 103 [g setFillColor:[state.color copy]]; 104 [array addObject:g]; 105} 106 107/* add list as stroked path object to layer 108 * we simply add everything in a single list ignoring all layers 109 */ 110- (void)addStrokeList:aList toLayer:(NSString*)layerName 111{ NSMutableArray *array = [self layerArrayWithName:layerName]; 112 VPath *g = [VPath path]; 113 114 [g addList:aList at:[[g list] count]]; 115 [g sortList]; 116 [g setFilled:NO]; 117 [g setColor:state.color]; 118 [g setFillColor:[state.color copy]]; // turning to filled will fill in the same color 119 [g setWidth:state.width]; 120 [array addObject:g]; 121} 122 123/* allocate a line object and add it to aList 124 */ 125- (void)addLine:(NSPoint)beg :(NSPoint)end toList:(NSMutableArray*)aList 126{ VLine *g; 127 128 g = [VLine line]; 129 [g setVertices:beg :end]; 130 [g setWidth:state.width]; 131 [g setColor:state.color]; 132 [aList addObject:g]; 133} 134- (void)addLine:(NSPoint)beg :(NSPoint)end toLayer:(NSString*)layerName 135{ NSMutableArray *array = [self layerArrayWithName:layerName]; 136 VLine *g; 137 138 if (!array) 139 array = [[layerList objectAtIndex:0] list]; 140 g = [VLine line]; 141 [g setVertices:beg :end]; 142 [g setWidth:state.width]; 143 [g setColor:state.color]; 144 [array addObject:g]; 145} 146 147/* allocate a line object and add it to aList 148 */ 149- (void)addLine3D:(V3Point)beg :(V3Point)end toList:(NSMutableArray*)aList 150{ VLine3D *g; 151 152 g = [VLine3D line3DWithPoints:beg :end]; 153 [g setWidth:state.width]; 154 [g setColor:state.color]; 155 [aList addObject:g]; 156} 157- (void)addLine3D:(V3Point)beg :(V3Point)end toLayer:(NSString*)layerName 158{ NSMutableArray *array = [self layerArrayWithName:layerName]; 159 VLine3D *g; 160 161 if (!array) 162 array = [[layerList objectAtIndex:0] list]; 163 g = [VLine3D line3DWithPoints:beg :end]; 164 [g setWidth:state.width]; 165 [g setColor:state.color]; 166 [array addObject:g]; 167} 168 169/* allocate an arc object and add it to aList 170 * center is the center of the arc 171 * start is the start point 172 * angle is the angle (negative for clockwise direction and positive for ccw direction) 173 */ 174- (void)addArc:(NSPoint)center :(NSPoint)start :(float)angle toList:(NSMutableArray*)aList 175{ VArc *g; 176 177 g = [VArc arc]; 178 [g setCenter:center start:start angle:angle]; 179 [g setWidth:state.width]; 180 [g setColor:state.color]; 181 [g setFillColor:[state.color copy]]; 182 [aList addObject:g]; 183} 184- (void)addArc:(NSPoint)center :(NSPoint)start :(float)angle toLayer:(NSString*)layerName 185{ NSMutableArray *array = [self layerArrayWithName:layerName]; 186 VArc *g; 187 188 if (!array) 189 array = [[layerList objectAtIndex:0] list]; 190 g = [VArc arc]; 191 [g setCenter:center start:start angle:angle]; 192 [g setWidth:state.width]; 193 [g setColor:state.color]; 194 [g setFillColor:[state.color copy]]; 195 [array addObject:g]; 196} 197 198/* allocate a curve object and add it to aList 199 */ 200- (void)addCurve:(NSPoint)p0 :(NSPoint)p1 :(NSPoint)p2 :(NSPoint)p3 toList:(NSMutableArray*)aList 201{ VCurve *g; 202 203 g = [VCurve curve]; 204 [g setVertices:p0 :p1 :p2 :p3]; 205 [g setWidth:state.width]; 206 [g setColor:state.color]; 207 [aList addObject:g]; 208} 209- (void)addCurve:(NSPoint)p0 :(NSPoint)p1 :(NSPoint)p2 :(NSPoint)p3 toLayer:(NSString*)layerName 210{ NSMutableArray *array = [self layerArrayWithName:layerName]; 211 VCurve *g; 212 213 if (!array) 214 array = [[layerList objectAtIndex:0] list]; 215 g = [VCurve curve]; 216 [g setVertices:p0 :p1 :p2 :p3]; 217 [g setWidth:state.width]; 218 [g setColor:state.color]; 219 [array addObject:g]; 220} 221 222/* 3D Surface 223 */ 224- (void)add3DFace:(V3Point*)pts toLayer:(NSString*)layerName 225{ 226 /* TODO: this should be a surface, not 4 lines */ 227 [self addLine3D:pts[0] :pts[1] toLayer:layerName]; 228 [self addLine3D:pts[1] :pts[2] toLayer:layerName]; 229 [self addLine3D:pts[2] :pts[3] toLayer:layerName]; 230 [self addLine3D:pts[3] :pts[0] toLayer:layerName]; 231} 232 233/* allocate a text object and add it to the layer 234 * parameter: text the text string 235 * font the font name 236 * angle rotation angle 237 * size the font size in pt 238 * ar aspect ratio height/width 239 * alignment see genFlags of MTEXT in DXF specs 240 * layerInfo the destination layer 241 */ 242- (void)addText:(NSString*)text :(NSString*)font :(float)angle :(float)size :(float)ar :(int)alignment at:(NSPoint)p toLayer:(NSString*)layerName 243{ NSMutableArray *array = [self layerArrayWithName:layerName]; 244 id fontObject; 245 VText *g = [VText textGraphic]; 246 NSRect bounds; 247 248 if (!array) 249 array = [[layerList objectAtIndex:0] list]; 250 [g setColor:state.color]; 251 [g setFillColor:[state.color copy]]; 252 if (!(fontObject = [NSFont fontWithName:font size:size])) 253 fontObject = [NSFont userFixedPitchFontOfSize:size]; // default 254 [g setFont:fontObject]; 255 [g setString:text]; 256 [g setRotAngle:angle]; 257 bounds = [g coordBounds]; 258 switch (alignment) 259 { 260 case 1: // top left 261 p.y -= bounds.size.height; 262 break; 263 case 2: // top center 264 p.x -= bounds.size.width / 2.0; 265 p.y -= bounds.size.height; 266 break; 267 case 3: // top right 268 p.x -= bounds.size.width; 269 p.y -= bounds.size.height; 270 break; 271 case 4: // middle left 272 p.y -= bounds.size.height / 2.0; 273 break; 274 case 5: // middle center 275 p.x -= bounds.size.width / 2.0; 276 p.y -= bounds.size.height / 2.0; 277 break; 278 case 6: // middle right 279 p.x -= bounds.size.width; 280 p.y -= bounds.size.height / 2.0; 281 break; 282 case 7: // bottom left 283 break; 284 case 8: // bottom center 285 p.x -= bounds.size.width / 2.0; 286 break; 287 case 9: // bottom right 288 p.x -= bounds.size.width; 289 } 290 if (alignment >= 7 ) // bottom aligned 291 [g setBaseOrigin:p]; 292 else 293 [g moveTo:p]; 294 [g setAspectRatio:ar]; 295 [array addObject:g]; 296 // [super addText:text :font :angle :size :ar at:p toList:aList]; 297} 298 299/* set the bounds 300 * we move the graphic to 0/0 and scale to acceptable size if necessary 301 * modified: 2006-12-11 302 */ 303- (void)setBounds:(NSRect)bounds 304{ int i, l, removed = 0; 305 NSPoint p; 306 NSPoint scaleCenter = NSZeroPoint; 307 float factor = 1.0; 308 BOOL scale = NO, delete = YES; 309 310 bounds = EnlargedRect(bounds, TOLERANCE); 311 312 p.x = - bounds.origin.x + MMToInternal(10.0); 313 p.y = - bounds.origin.y + MMToInternal(10.0); 314 315#if !defined(GNUSTEP_BASE_VERSION) && !defined(__APPLE__) // OpenStep 4.2 316 if ( Max(bounds.size.width, bounds.size.height) > 10000.0 ) 317 { 318 NSRunAlertPanel(@"", DXFSIZE_STRING, OK_STRING, nil, nil); 319 factor = Max(bounds.size.width, bounds.size.height); 320 while ( factor > 10000.0 ) 321 factor /= 10.0; 322 factor = factor / Max(bounds.size.width, bounds.size.height); 323 scale = YES; 324 } 325#endif 326 327 for (l=0; l<(int)[layerList count]; l++) 328 { NSMutableArray *array = [[layerList objectAtIndex:l] list]; 329 330 for (i=[array count]-1; i>=0; i--) 331 { id obj = [array objectAtIndex:i]; 332 333 /* object out of bounds */ 334 if (!vhfContainsRect(bounds, [obj bounds]) && !vhfIntersectsRect(bounds, [obj bounds])) 335 { 336 if (removed || (delete && 337 NSRunAlertPanel(@"", DXFIMPORTOUTOFBOUNDS_STRING, DELETE_STRING, KEEP_STRING, nil) 338 == NSAlertDefaultReturn)) 339 { 340 [array removeObjectAtIndex:i]; 341 removed ++; 342 continue; 343 } 344 else 345 delete = NO; 346 } 347 [obj moveBy:p]; 348 if ( scale ) 349 [obj scale:factor :factor withCenter:scaleCenter]; 350 } 351 /* remove empty layers */ 352 if (![array count]) 353 { [layerList removeObjectAtIndex:l]; 354 l--; 355 } 356 } 357 if (removed) 358 NSLog(@"DXF-Import: %d Objects removed, which are exceeding drawing extents!", removed); 359} 360 361@end 362