1 : /******************************************************************************
2 : * $Id: ogrdxflayer.cpp 18409 2009-12-29 01:10:00Z warmerdam $
3 : *
4 : * Project: DXF Translator
5 : * Purpose: Implements OGRDXFLayer class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_dxf.h"
31 : #include "cpl_conv.h"
32 :
33 : CPL_CVSID("$Id: ogrdxflayer.cpp 18409 2009-12-29 01:10:00Z warmerdam $");
34 :
35 : #ifndef PI
36 : #define PI 3.14159265358979323846
37 : #endif
38 :
39 : /************************************************************************/
40 : /* OGRDXFLayer() */
41 : /************************************************************************/
42 :
43 1 : OGRDXFLayer::OGRDXFLayer( OGRDXFDataSource *poDS )
44 :
45 : {
46 1 : this->poDS = poDS;
47 :
48 1 : iNextFID = 0;
49 :
50 1 : poFeatureDefn = new OGRFeatureDefn( "entities" );
51 1 : poFeatureDefn->Reference();
52 :
53 1 : OGRFieldDefn oLayerField( "Layer", OFTString );
54 1 : poFeatureDefn->AddFieldDefn( &oLayerField );
55 :
56 1 : OGRFieldDefn oClassField( "SubClasses", OFTString );
57 1 : poFeatureDefn->AddFieldDefn( &oClassField );
58 :
59 1 : OGRFieldDefn oExtendedField( "ExtendedEntity", OFTString );
60 1 : poFeatureDefn->AddFieldDefn( &oExtendedField );
61 :
62 1 : OGRFieldDefn oLinetypeField( "Linetype", OFTString );
63 1 : poFeatureDefn->AddFieldDefn( &oLinetypeField );
64 :
65 1 : OGRFieldDefn oEntityHandleField( "EntityHandle", OFTString );
66 1 : poFeatureDefn->AddFieldDefn( &oEntityHandleField );
67 :
68 1 : OGRFieldDefn oTextField( "Text", OFTString );
69 1 : poFeatureDefn->AddFieldDefn( &oTextField );
70 1 : }
71 :
72 : /************************************************************************/
73 : /* ~OGRDXFLayer() */
74 : /************************************************************************/
75 :
76 2 : OGRDXFLayer::~OGRDXFLayer()
77 :
78 : {
79 1 : ClearPendingFeatures();
80 1 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
81 : {
82 : CPLDebug( "DXF", "%d features read on layer '%s'.",
83 : (int) m_nFeaturesRead,
84 1 : poFeatureDefn->GetName() );
85 : }
86 :
87 1 : if( poFeatureDefn )
88 1 : poFeatureDefn->Release();
89 2 : }
90 :
91 : /************************************************************************/
92 : /* ClearPendingFeatures() */
93 : /************************************************************************/
94 :
95 5 : void OGRDXFLayer::ClearPendingFeatures()
96 :
97 : {
98 10 : while( !apoPendingFeatures.empty() )
99 : {
100 0 : delete apoPendingFeatures.top();
101 0 : apoPendingFeatures.pop();
102 : }
103 5 : }
104 :
105 : /************************************************************************/
106 : /* ResetReading() */
107 : /************************************************************************/
108 :
109 4 : void OGRDXFLayer::ResetReading()
110 :
111 : {
112 4 : iNextFID = 0;
113 4 : ClearPendingFeatures();
114 4 : poDS->RestartEntities();
115 4 : }
116 :
117 : /************************************************************************/
118 : /* TranslateGenericProperty() */
119 : /* */
120 : /* Try and convert entity properties handled similarly for most */
121 : /* or all entity types. */
122 : /************************************************************************/
123 :
124 166 : void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature,
125 : int nCode, char *pszValue )
126 :
127 : {
128 166 : switch( nCode )
129 : {
130 : case 8:
131 18 : poFeature->SetField( "Layer", pszValue );
132 18 : break;
133 :
134 : case 100:
135 : {
136 44 : CPLString osSubClass = poFeature->GetFieldAsString("SubClasses");
137 44 : if( osSubClass.size() > 0 )
138 26 : osSubClass += ":";
139 44 : osSubClass += pszValue;
140 44 : poFeature->SetField( "SubClasses", osSubClass.c_str() );
141 : }
142 44 : break;
143 :
144 : case 62:
145 18 : oStyleProperties["Color"] = pszValue;
146 18 : break;
147 :
148 : case 6:
149 18 : poFeature->SetField( "Linetype", pszValue );
150 18 : break;
151 :
152 : case 370:
153 : case 39:
154 18 : oStyleProperties["LineWeight"] = pszValue;
155 18 : break;
156 :
157 : case 5:
158 18 : poFeature->SetField( "EntityHandle", pszValue );
159 18 : break;
160 :
161 : // Extended entity data
162 : case 1000:
163 : case 1002:
164 : case 1004:
165 : case 1005:
166 : case 1040:
167 : case 1041:
168 : case 1070:
169 : case 1071:
170 : {
171 0 : CPLString osAggregate = poFeature->GetFieldAsString("ExtendedEntity");
172 :
173 0 : if( osAggregate.size() > 0 )
174 0 : osAggregate += " ";
175 0 : osAggregate += pszValue;
176 :
177 0 : poFeature->SetField( "ExtendedEntity", osAggregate );
178 : }
179 : break;
180 :
181 : default:
182 : break;
183 : }
184 166 : }
185 :
186 : /************************************************************************/
187 : /* PrepareLineStyle() */
188 : /* */
189 : /* For now I don't bother trying to translate the dash/dot */
190 : /* linetype into the style string since I'm not aware of any */
191 : /* application that will honour it anyways. */
192 : /************************************************************************/
193 :
194 14 : void OGRDXFLayer::PrepareLineStyle( OGRFeature *poFeature )
195 :
196 : {
197 14 : CPLString osLayer = poFeature->GetFieldAsString("Layer");
198 :
199 : /* -------------------------------------------------------------------- */
200 : /* Work out the color for this feature. */
201 : /* -------------------------------------------------------------------- */
202 14 : int nColor = 256;
203 :
204 14 : if( oStyleProperties.count("Color") > 0 )
205 14 : nColor = atoi(oStyleProperties["Color"]);
206 :
207 : // Use layer color?
208 14 : if( nColor < 1 || nColor > 255 )
209 : {
210 14 : const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
211 14 : if( pszValue != NULL )
212 14 : nColor = atoi(pszValue);
213 : }
214 :
215 14 : if( nColor < 1 || nColor > 255 )
216 : return;
217 :
218 : /* -------------------------------------------------------------------- */
219 : /* Get line weight if available. */
220 : /* -------------------------------------------------------------------- */
221 14 : double dfWeight = 0.0;
222 :
223 14 : if( oStyleProperties.count("LineWeight") > 0 )
224 : {
225 14 : CPLString osWeight = oStyleProperties["LineWeight"];
226 :
227 14 : if( osWeight == "-1" )
228 14 : osWeight = poDS->LookupLayerProperty(osLayer,"LineWeight");
229 :
230 14 : dfWeight = atof(osWeight) / 100.0;
231 : }
232 :
233 : /* -------------------------------------------------------------------- */
234 : /* Format the style string. */
235 : /* -------------------------------------------------------------------- */
236 14 : CPLString osStyle;
237 14 : const unsigned char *pabyDXFColors = OGRDXFDriver::GetDXFColorTable();
238 :
239 : osStyle.Printf( "PEN(c:#%02x%02x%02x",
240 14 : pabyDXFColors[nColor*3+0],
241 14 : pabyDXFColors[nColor*3+1],
242 42 : pabyDXFColors[nColor*3+2] );
243 :
244 14 : if( dfWeight > 0.0 )
245 0 : osStyle += CPLString().Printf( ",w:%.2gmm", dfWeight );
246 :
247 14 : osStyle += ")";
248 :
249 14 : poFeature->SetStyleString( osStyle );
250 : }
251 :
252 : /************************************************************************/
253 : /* TranslateMTEXT() */
254 : /************************************************************************/
255 :
256 2 : OGRFeature *OGRDXFLayer::TranslateMTEXT()
257 :
258 : {
259 : char szLineBuf[257];
260 : int nCode;
261 2 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
262 2 : double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
263 2 : double dfAngle = 0.0;
264 2 : double dfHeight = 0.0;
265 2 : int nAttachmentPoint = -1;
266 2 : CPLString osText;
267 :
268 42 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
269 : {
270 38 : switch( nCode )
271 : {
272 : case 10:
273 2 : dfX = atof(szLineBuf);
274 2 : break;
275 :
276 : case 20:
277 2 : dfY = atof(szLineBuf);
278 2 : break;
279 :
280 : case 30:
281 2 : dfZ = atof(szLineBuf);
282 2 : break;
283 :
284 : case 40:
285 2 : dfHeight = atof(szLineBuf);
286 2 : break;
287 :
288 : case 71:
289 2 : nAttachmentPoint = atoi(szLineBuf);
290 2 : break;
291 :
292 : case 1:
293 : case 3:
294 2 : osText += szLineBuf;
295 2 : break;
296 :
297 : case 50:
298 2 : dfAngle = atof(szLineBuf);
299 2 : break;
300 :
301 : default:
302 24 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
303 : break;
304 : }
305 : }
306 :
307 2 : if( nCode == 0 )
308 2 : poDS->UnreadValue();
309 :
310 2 : poFeature->SetField( "Text", osText );
311 2 : poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY, dfZ ) );
312 :
313 : /* -------------------------------------------------------------------- */
314 : /* Work out the color for this feature. */
315 : /* -------------------------------------------------------------------- */
316 2 : int nColor = 256;
317 :
318 2 : if( oStyleProperties.count("Color") > 0 )
319 2 : nColor = atoi(oStyleProperties["Color"]);
320 :
321 : // Use layer color?
322 2 : if( nColor < 1 || nColor > 255 )
323 : {
324 2 : CPLString osLayer = poFeature->GetFieldAsString("Layer");
325 2 : const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
326 2 : if( pszValue != NULL )
327 2 : nColor = atoi(pszValue);
328 : }
329 :
330 : /* -------------------------------------------------------------------- */
331 : /* Prepare style string. */
332 : /* -------------------------------------------------------------------- */
333 2 : CPLString osStyle;
334 :
335 2 : osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\"",osText.c_str());
336 :
337 2 : if( dfAngle != 0.0 )
338 2 : osStyle += CPLString().Printf(",a:%.3g", dfAngle);
339 :
340 2 : if( dfHeight != 0.0 )
341 2 : osStyle += CPLString().Printf(",s:%.3gg", dfHeight);
342 :
343 2 : if( nAttachmentPoint >= 0 && nAttachmentPoint <= 9 )
344 : {
345 : const static int anAttachmentMap[10] =
346 : { -1, 7, 8, 9, 4, 5, 6, 1, 2, 3 };
347 :
348 : osStyle +=
349 2 : CPLString().Printf(",p:%d", anAttachmentMap[nAttachmentPoint]);
350 : }
351 :
352 2 : if( nColor > 0 && nColor < 256 )
353 : {
354 2 : const unsigned char *pabyDXFColors = OGRDXFDriver::GetDXFColorTable();
355 : osStyle +=
356 : CPLString().Printf( ",c:#%02x%02x%02x",
357 2 : pabyDXFColors[nColor*3+0],
358 2 : pabyDXFColors[nColor*3+1],
359 6 : pabyDXFColors[nColor*3+2] );
360 : }
361 :
362 2 : osStyle += ")";
363 :
364 2 : poFeature->SetStyleString( osStyle );
365 :
366 2 : return poFeature;
367 : }
368 :
369 : /************************************************************************/
370 : /* TranslateTEXT() */
371 : /************************************************************************/
372 :
373 0 : OGRFeature *OGRDXFLayer::TranslateTEXT()
374 :
375 : {
376 : char szLineBuf[257];
377 : int nCode;
378 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
379 0 : double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
380 0 : double dfAngle = 0.0;
381 0 : double dfHeight = 0.0;
382 0 : CPLString osText;
383 :
384 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
385 : {
386 0 : switch( nCode )
387 : {
388 : case 10:
389 0 : dfX = atof(szLineBuf);
390 0 : break;
391 :
392 : case 20:
393 0 : dfY = atof(szLineBuf);
394 0 : break;
395 :
396 : case 30:
397 0 : dfZ = atof(szLineBuf);
398 0 : break;
399 :
400 : case 40:
401 0 : dfHeight = atof(szLineBuf);
402 0 : break;
403 :
404 : case 1:
405 : case 3:
406 0 : osText += szLineBuf;
407 0 : break;
408 :
409 : case 50:
410 0 : dfAngle = atof(szLineBuf);
411 0 : break;
412 :
413 : default:
414 0 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
415 : break;
416 : }
417 : }
418 :
419 0 : if( nCode == 0 )
420 0 : poDS->UnreadValue();
421 :
422 0 : poFeature->SetField( "Text", osText );
423 0 : poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY, dfZ ) );
424 :
425 : /* -------------------------------------------------------------------- */
426 : /* Prepare style string. */
427 : /* -------------------------------------------------------------------- */
428 0 : CPLString osStyle;
429 :
430 0 : osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\"",osText.c_str());
431 :
432 0 : if( dfAngle != 0.0 )
433 0 : osStyle += CPLString().Printf(",a:%.3g", dfAngle);
434 :
435 0 : if( dfHeight != 0.0 )
436 0 : osStyle += CPLString().Printf(",s:%.3gg", dfHeight);
437 :
438 : // add color!
439 :
440 0 : osStyle += ")";
441 :
442 0 : poFeature->SetStyleString( osStyle );
443 :
444 0 : return poFeature;
445 : }
446 :
447 : /************************************************************************/
448 : /* TranslatePOINT() */
449 : /************************************************************************/
450 :
451 2 : OGRFeature *OGRDXFLayer::TranslatePOINT()
452 :
453 : {
454 : char szLineBuf[257];
455 : int nCode;
456 2 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
457 2 : double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
458 :
459 24 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
460 : {
461 20 : switch( nCode )
462 : {
463 : case 10:
464 2 : dfX = atof(szLineBuf);
465 2 : break;
466 :
467 : case 20:
468 2 : dfY = atof(szLineBuf);
469 2 : break;
470 :
471 : case 30:
472 2 : dfZ = atof(szLineBuf);
473 2 : break;
474 :
475 : default:
476 14 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
477 : break;
478 : }
479 : }
480 :
481 2 : poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY, dfZ ) );
482 :
483 2 : if( nCode == 0 )
484 2 : poDS->UnreadValue();
485 :
486 2 : return poFeature;
487 : }
488 :
489 : /************************************************************************/
490 : /* TranslateLINE() */
491 : /************************************************************************/
492 :
493 4 : OGRFeature *OGRDXFLayer::TranslateLINE()
494 :
495 : {
496 : char szLineBuf[257];
497 : int nCode;
498 4 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
499 4 : double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0;
500 4 : double dfX2 = 0.0, dfY2 = 0.0, dfZ2 = 0.0;
501 :
502 : /* -------------------------------------------------------------------- */
503 : /* Process values. */
504 : /* -------------------------------------------------------------------- */
505 60 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
506 : {
507 52 : switch( nCode )
508 : {
509 : case 10:
510 4 : dfX1 = atof(szLineBuf);
511 4 : break;
512 :
513 : case 11:
514 4 : dfX2 = atof(szLineBuf);
515 4 : break;
516 :
517 : case 20:
518 4 : dfY1 = atof(szLineBuf);
519 4 : break;
520 :
521 : case 21:
522 4 : dfY2 = atof(szLineBuf);
523 4 : break;
524 :
525 : case 30:
526 4 : dfZ1 = atof(szLineBuf);
527 4 : break;
528 :
529 : case 31:
530 4 : dfZ2 = atof(szLineBuf);
531 4 : break;
532 :
533 : default:
534 28 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
535 : break;
536 : }
537 : }
538 :
539 4 : if( nCode == 0 )
540 4 : poDS->UnreadValue();
541 :
542 : /* -------------------------------------------------------------------- */
543 : /* Create geometry */
544 : /* -------------------------------------------------------------------- */
545 4 : OGRLineString *poLS = new OGRLineString();
546 4 : poLS->addPoint( dfX1, dfY1, dfZ1 );
547 4 : poLS->addPoint( dfX2, dfY2, dfZ2 );
548 :
549 4 : poFeature->SetGeometryDirectly( poLS );
550 :
551 4 : PrepareLineStyle( poFeature );
552 :
553 4 : return poFeature;
554 : }
555 :
556 : /************************************************************************/
557 : /* TranslateLWPOLYLINE() */
558 : /************************************************************************/
559 :
560 0 : OGRFeature *OGRDXFLayer::TranslateLWPOLYLINE()
561 :
562 : {
563 : char szLineBuf[257];
564 : int nCode;
565 0 : int nPolylineFlag = 0;
566 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
567 0 : OGRLineString *poLS = new OGRLineString();
568 0 : double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
569 0 : int bHaveX = FALSE, bHaveY = FALSE;
570 :
571 : /* -------------------------------------------------------------------- */
572 : /* Collect information from the LWPOLYLINE object itself. */
573 : /* -------------------------------------------------------------------- */
574 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
575 : {
576 0 : switch( nCode )
577 : {
578 : case 70:
579 0 : nPolylineFlag = atoi(szLineBuf);
580 0 : break;
581 :
582 : case 10:
583 0 : if( bHaveX && bHaveY )
584 : {
585 0 : poLS->addPoint( dfX, dfY, dfZ );
586 0 : bHaveY = FALSE;
587 : }
588 0 : dfX = atof(szLineBuf);
589 0 : bHaveX = TRUE;
590 0 : break;
591 :
592 : case 20:
593 0 : if( bHaveX && bHaveY )
594 : {
595 0 : poLS->addPoint( dfX, dfY, dfZ );
596 0 : bHaveX = FALSE;
597 : }
598 0 : dfY = atof(szLineBuf);
599 0 : bHaveY = TRUE;
600 0 : break;
601 :
602 : case 30:
603 0 : dfZ = atof(szLineBuf);
604 0 : break;
605 :
606 : default:
607 0 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
608 : break;
609 : }
610 : }
611 :
612 0 : poDS->UnreadValue();
613 :
614 0 : if( bHaveX && bHaveY )
615 0 : poLS->addPoint( dfX, dfY, dfZ );
616 :
617 : /* -------------------------------------------------------------------- */
618 : /* Close polyline as polygon if necessary. */
619 : /* -------------------------------------------------------------------- */
620 0 : if( (nPolylineFlag & 0x01)
621 : && poLS->getNumPoints() > 0
622 : && (poLS->getX(poLS->getNumPoints()-1) != poLS->getX(0)
623 : || poLS->getY(poLS->getNumPoints()-1) != poLS->getY(0)) )
624 : {
625 0 : poLS->addPoint( poLS->getX(0), poLS->getY(0), poLS->getZ(0) );
626 : }
627 :
628 0 : poFeature->SetGeometryDirectly( poLS );
629 :
630 0 : PrepareLineStyle( poFeature );
631 :
632 0 : return poFeature;
633 : }
634 :
635 : /************************************************************************/
636 : /* TranslatePOLYLINE() */
637 : /* */
638 : /* We also capture the following VERTEXes. */
639 : /************************************************************************/
640 :
641 0 : OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
642 :
643 : {
644 : char szLineBuf[257];
645 : int nCode;
646 0 : int nPolylineFlag = 0;
647 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
648 :
649 : /* -------------------------------------------------------------------- */
650 : /* Collect information from the POLYLINE object itself. */
651 : /* -------------------------------------------------------------------- */
652 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
653 : {
654 0 : switch( nCode )
655 : {
656 : case 70:
657 0 : nPolylineFlag = atoi(szLineBuf);
658 0 : break;
659 :
660 : default:
661 0 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
662 : break;
663 : }
664 : }
665 :
666 : /* -------------------------------------------------------------------- */
667 : /* Collect VERTEXes as a linestring. */
668 : /* -------------------------------------------------------------------- */
669 0 : OGRLineString *poLS = new OGRLineString();
670 0 : double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
671 :
672 0 : while( nCode == 0 && !EQUAL(szLineBuf,"SEQEND") )
673 : {
674 : // Eat non-vertex objects.
675 0 : if( !EQUAL(szLineBuf,"VERTEX") )
676 : {
677 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf)))>0 ) {}
678 0 : continue;
679 : }
680 :
681 : // process a Vertex
682 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
683 : {
684 0 : switch( nCode )
685 : {
686 : case 10:
687 0 : dfX = atof(szLineBuf);
688 0 : break;
689 :
690 : case 20:
691 0 : dfY = atof(szLineBuf);
692 0 : break;
693 :
694 : case 30:
695 0 : dfZ = atof(szLineBuf);
696 : break;
697 :
698 : default:
699 : break;
700 : }
701 : }
702 :
703 0 : poLS->addPoint( dfX, dfY, dfZ );
704 : }
705 :
706 : /* -------------------------------------------------------------------- */
707 : /* Close polyline as polygon if necessary. */
708 : /* -------------------------------------------------------------------- */
709 0 : if( (nPolylineFlag & 0x01)
710 : && poLS->getNumPoints() > 0
711 : && (poLS->getX(poLS->getNumPoints()-1) != poLS->getX(0)
712 : || poLS->getY(poLS->getNumPoints()-1) != poLS->getY(0)) )
713 : {
714 0 : poLS->addPoint( poLS->getX(0), poLS->getY(0), poLS->getZ(0) );
715 : }
716 :
717 0 : poFeature->SetGeometryDirectly( poLS );
718 :
719 0 : PrepareLineStyle( poFeature );
720 :
721 0 : return poFeature;
722 : }
723 :
724 : /************************************************************************/
725 : /* TranslateCIRCLE() */
726 : /************************************************************************/
727 :
728 0 : OGRFeature *OGRDXFLayer::TranslateCIRCLE()
729 :
730 : {
731 : char szLineBuf[257];
732 : int nCode;
733 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
734 0 : double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0, dfRadius = 0.0;
735 :
736 : /* -------------------------------------------------------------------- */
737 : /* Process values. */
738 : /* -------------------------------------------------------------------- */
739 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
740 : {
741 0 : switch( nCode )
742 : {
743 : case 10:
744 0 : dfX1 = atof(szLineBuf);
745 0 : break;
746 :
747 : case 20:
748 0 : dfY1 = atof(szLineBuf);
749 0 : break;
750 :
751 : case 30:
752 0 : dfZ1 = atof(szLineBuf);
753 0 : break;
754 :
755 : case 40:
756 0 : dfRadius = atof(szLineBuf);
757 0 : break;
758 :
759 : default:
760 0 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
761 : break;
762 : }
763 : }
764 :
765 0 : if( nCode == 0 )
766 0 : poDS->UnreadValue();
767 :
768 : /* -------------------------------------------------------------------- */
769 : /* Create geometry */
770 : /* -------------------------------------------------------------------- */
771 : poFeature->SetGeometryDirectly(
772 : OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1,
773 : dfRadius, dfRadius, 0.0,
774 : 0.0, 360.0,
775 0 : 0.0 ) );
776 :
777 0 : PrepareLineStyle( poFeature );
778 :
779 0 : return poFeature;
780 : }
781 :
782 : /************************************************************************/
783 : /* TranslateELLIPSE() */
784 : /************************************************************************/
785 :
786 4 : OGRFeature *OGRDXFLayer::TranslateELLIPSE()
787 :
788 : {
789 : char szLineBuf[257];
790 : int nCode;
791 4 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
792 4 : double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0, dfRatio = 0.0;
793 4 : double dfStartAngle = 0.0, dfEndAngle = 360.0;
794 4 : double dfAxisX=0.0, dfAxisY=0.0, dfAxisZ=0.0;
795 :
796 : /* -------------------------------------------------------------------- */
797 : /* Process values. */
798 : /* -------------------------------------------------------------------- */
799 72 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
800 : {
801 64 : switch( nCode )
802 : {
803 : case 10:
804 4 : dfX1 = atof(szLineBuf);
805 4 : break;
806 :
807 : case 20:
808 4 : dfY1 = atof(szLineBuf);
809 4 : break;
810 :
811 : case 30:
812 4 : dfZ1 = atof(szLineBuf);
813 4 : break;
814 :
815 : case 11:
816 4 : dfAxisX = atof(szLineBuf);
817 4 : break;
818 :
819 : case 21:
820 4 : dfAxisY = atof(szLineBuf);
821 4 : break;
822 :
823 : case 31:
824 4 : dfAxisZ = atof(szLineBuf);
825 4 : break;
826 :
827 : case 40:
828 4 : dfRatio = atof(szLineBuf);
829 4 : break;
830 :
831 : case 41:
832 4 : dfEndAngle = -1 * atof(szLineBuf) * 180.0 / PI;
833 4 : break;
834 :
835 : case 42:
836 4 : dfStartAngle = -1 * atof(szLineBuf) * 180.0 / PI;
837 4 : break;
838 :
839 : default:
840 28 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
841 : break;
842 : }
843 : }
844 :
845 4 : if( nCode == 0 )
846 4 : poDS->UnreadValue();
847 :
848 : /* -------------------------------------------------------------------- */
849 : /* Compute primary and secondary axis lengths, and the angle of */
850 : /* rotation for the ellipse. */
851 : /* -------------------------------------------------------------------- */
852 : double dfPrimaryRadius, dfSecondaryRadius;
853 : double dfRotation;
854 :
855 4 : if( dfStartAngle > dfEndAngle )
856 0 : dfEndAngle += 360.0;
857 :
858 : dfPrimaryRadius = sqrt( dfAxisX * dfAxisX
859 : + dfAxisY * dfAxisY
860 4 : + dfAxisZ * dfAxisZ );
861 :
862 4 : dfSecondaryRadius = dfRatio * dfPrimaryRadius;
863 :
864 4 : dfRotation = -1 * atan2( dfAxisY, dfAxisX ) * 180 / PI;
865 :
866 : /* -------------------------------------------------------------------- */
867 : /* Create geometry */
868 : /* -------------------------------------------------------------------- */
869 : poFeature->SetGeometryDirectly(
870 : OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1,
871 : dfPrimaryRadius,
872 : dfSecondaryRadius,
873 : dfRotation,
874 : dfStartAngle, dfEndAngle,
875 4 : 0.0 ) );
876 :
877 4 : PrepareLineStyle( poFeature );
878 :
879 4 : return poFeature;
880 : }
881 :
882 : /************************************************************************/
883 : /* TranslateARC() */
884 : /************************************************************************/
885 :
886 2 : OGRFeature *OGRDXFLayer::TranslateARC()
887 :
888 : {
889 : char szLineBuf[257];
890 : int nCode;
891 2 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
892 2 : double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0, dfRadius = 0.0;
893 2 : double dfStartAngle = 0.0, dfEndAngle = 360.0;
894 :
895 : /* -------------------------------------------------------------------- */
896 : /* Process values. */
897 : /* -------------------------------------------------------------------- */
898 32 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
899 : {
900 28 : switch( nCode )
901 : {
902 : case 10:
903 2 : dfX1 = atof(szLineBuf);
904 2 : break;
905 :
906 : case 20:
907 2 : dfY1 = atof(szLineBuf);
908 2 : break;
909 :
910 : case 30:
911 2 : dfZ1 = atof(szLineBuf);
912 2 : break;
913 :
914 : case 40:
915 2 : dfRadius = atof(szLineBuf);
916 2 : break;
917 :
918 : case 50:
919 2 : dfEndAngle = -1 * atof(szLineBuf);
920 2 : break;
921 :
922 : case 51:
923 2 : dfStartAngle = -1 * atof(szLineBuf);
924 2 : break;
925 :
926 : default:
927 16 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
928 : break;
929 : }
930 : }
931 :
932 2 : if( nCode == 0 )
933 2 : poDS->UnreadValue();
934 :
935 : /* -------------------------------------------------------------------- */
936 : /* Create geometry */
937 : /* -------------------------------------------------------------------- */
938 2 : if( dfStartAngle > dfEndAngle )
939 2 : dfEndAngle += 360.0;
940 :
941 : poFeature->SetGeometryDirectly(
942 : OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1,
943 : dfRadius, dfRadius, 0.0,
944 : dfStartAngle, dfEndAngle,
945 2 : 0.0 ) );
946 :
947 2 : PrepareLineStyle( poFeature );
948 :
949 2 : return poFeature;
950 : }
951 :
952 : /************************************************************************/
953 : /* TranslateSPLINE() */
954 : /************************************************************************/
955 :
956 : void rbspline(int npts,int k,int p1,double b[],double h[], double p[]);
957 : void rbsplinu(int npts,int k,int p1,double b[],double h[], double p[]);
958 :
959 0 : OGRFeature *OGRDXFLayer::TranslateSPLINE()
960 :
961 : {
962 : char szLineBuf[257];
963 0 : int nCode, nDegree = -1, nFlags = -1, bClosed = FALSE, i;
964 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
965 0 : std::vector<double> adfControlPoints;
966 :
967 0 : adfControlPoints.push_back(0.0);
968 :
969 : /* -------------------------------------------------------------------- */
970 : /* Process values. */
971 : /* -------------------------------------------------------------------- */
972 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
973 : {
974 0 : switch( nCode )
975 : {
976 : case 10:
977 0 : adfControlPoints.push_back( atof(szLineBuf) );
978 0 : break;
979 :
980 : case 20:
981 0 : adfControlPoints.push_back( atof(szLineBuf) );
982 0 : adfControlPoints.push_back( 0.0 );
983 0 : break;
984 :
985 : case 70:
986 0 : nFlags = atoi(szLineBuf);
987 0 : if( nFlags & 1 )
988 0 : bClosed = TRUE;
989 0 : break;
990 :
991 : case 71:
992 0 : nDegree = atoi(szLineBuf);
993 0 : break;
994 :
995 : default:
996 0 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
997 : break;
998 : }
999 : }
1000 :
1001 0 : if( nCode == 0 )
1002 0 : poDS->UnreadValue();
1003 :
1004 0 : if( bClosed )
1005 : {
1006 0 : for( i = 0; i < nDegree; i++ )
1007 : {
1008 0 : adfControlPoints.push_back( adfControlPoints[i*3+1] );
1009 0 : adfControlPoints.push_back( adfControlPoints[i*3+2] );
1010 0 : adfControlPoints.push_back( adfControlPoints[i*3+3] );
1011 : }
1012 : }
1013 :
1014 : /* -------------------------------------------------------------------- */
1015 : /* Interpolate spline */
1016 : /* -------------------------------------------------------------------- */
1017 0 : int nControlPoints = adfControlPoints.size() / 3;
1018 0 : std::vector<double> h, p;
1019 :
1020 0 : h.push_back(1.0);
1021 0 : for( i = 0; i < nControlPoints; i++ )
1022 0 : h.push_back( 1.0 );
1023 :
1024 : // resolution:
1025 : //int p1 = getGraphicVariableInt("$SPLINESEGS", 8) * npts;
1026 0 : int p1 = nControlPoints * 8;
1027 :
1028 0 : p.push_back( 0.0 );
1029 0 : for( i = 0; i < 3*p1; i++ )
1030 0 : p.push_back( 0.0 );
1031 :
1032 0 : if( bClosed )
1033 : rbsplinu( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]),
1034 0 : &(h[0]), &(p[0]) );
1035 : else
1036 : rbspline( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]),
1037 0 : &(h[0]), &(p[0]) );
1038 :
1039 : /* -------------------------------------------------------------------- */
1040 : /* Turn into OGR geometry. */
1041 : /* -------------------------------------------------------------------- */
1042 0 : OGRLineString *poLS = new OGRLineString();
1043 :
1044 0 : poLS->setNumPoints( p1 );
1045 0 : for( i = 0; i < p1; i++ )
1046 0 : poLS->setPoint( i, p[i*3+1], p[i*3+2] );
1047 :
1048 0 : poFeature->SetGeometryDirectly( poLS );
1049 :
1050 0 : PrepareLineStyle( poFeature );
1051 :
1052 0 : return poFeature;
1053 : }
1054 :
1055 : /************************************************************************/
1056 : /* GeometryInsertTransformer */
1057 : /************************************************************************/
1058 :
1059 : class GeometryInsertTransformer : public OGRCoordinateTransformation
1060 0 : {
1061 : public:
1062 0 : GeometryInsertTransformer() :
1063 : dfXOffset(0),dfYOffset(0),dfZOffset(0),
1064 : dfXScale(1.0),dfYScale(1.0),dfZScale(1.0),
1065 0 : dfAngle(0.0) {}
1066 :
1067 : double dfXOffset;
1068 : double dfYOffset;
1069 : double dfZOffset;
1070 : double dfXScale;
1071 : double dfYScale;
1072 : double dfZScale;
1073 : double dfAngle;
1074 :
1075 0 : OGRSpatialReference *GetSourceCS() { return NULL; }
1076 0 : OGRSpatialReference *GetTargetCS() { return NULL; }
1077 0 : int Transform( int nCount,
1078 : double *x, double *y, double *z )
1079 0 : { return TransformEx( nCount, x, y, z, NULL ); }
1080 :
1081 0 : int TransformEx( int nCount,
1082 : double *x, double *y, double *z = NULL,
1083 : int *pabSuccess = NULL )
1084 : {
1085 : int i;
1086 0 : for( i = 0; i < nCount; i++ )
1087 : {
1088 : double dfXNew, dfYNew;
1089 :
1090 0 : x[i] *= dfXScale;
1091 0 : y[i] *= dfYScale;
1092 0 : z[i] *= dfZScale;
1093 :
1094 0 : dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
1095 0 : dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
1096 :
1097 0 : x[i] = dfXNew;
1098 0 : y[i] = dfYNew;
1099 :
1100 0 : x[i] += dfXOffset;
1101 0 : y[i] += dfYOffset;
1102 0 : z[i] += dfZOffset;
1103 :
1104 0 : if( pabSuccess )
1105 0 : pabSuccess[i] = TRUE;
1106 : }
1107 0 : return TRUE;
1108 : }
1109 : };
1110 :
1111 : /************************************************************************/
1112 : /* TranslateINSERT() */
1113 : /************************************************************************/
1114 :
1115 0 : OGRFeature *OGRDXFLayer::TranslateINSERT()
1116 :
1117 : {
1118 : char szLineBuf[257];
1119 : int nCode;
1120 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
1121 0 : GeometryInsertTransformer oTransformer;
1122 0 : CPLString osBlockName;
1123 :
1124 : /* -------------------------------------------------------------------- */
1125 : /* Process values. */
1126 : /* -------------------------------------------------------------------- */
1127 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
1128 : {
1129 0 : switch( nCode )
1130 : {
1131 : case 10:
1132 0 : oTransformer.dfXOffset = atof(szLineBuf);
1133 0 : break;
1134 :
1135 : case 20:
1136 0 : oTransformer.dfYOffset = atof(szLineBuf);
1137 0 : break;
1138 :
1139 : case 30:
1140 0 : oTransformer.dfZOffset = atof(szLineBuf);
1141 0 : break;
1142 :
1143 : case 41:
1144 0 : oTransformer.dfXScale = atof(szLineBuf);
1145 0 : break;
1146 :
1147 : case 42:
1148 0 : oTransformer.dfYScale = atof(szLineBuf);
1149 0 : break;
1150 :
1151 : case 43:
1152 0 : oTransformer.dfZScale = atof(szLineBuf);
1153 0 : break;
1154 :
1155 : case 50:
1156 0 : oTransformer.dfAngle = atof(szLineBuf) * PI / 180.0;
1157 0 : break;
1158 :
1159 : case 2:
1160 0 : osBlockName = szLineBuf;
1161 0 : break;
1162 :
1163 : default:
1164 0 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
1165 : break;
1166 : }
1167 : }
1168 :
1169 0 : if( nCode == 0 )
1170 0 : poDS->UnreadValue();
1171 :
1172 : /* -------------------------------------------------------------------- */
1173 : /* Lookup the block. */
1174 : /* -------------------------------------------------------------------- */
1175 0 : DXFBlockDefinition *poBlock = poDS->LookupBlock( osBlockName );
1176 :
1177 0 : if( poBlock == NULL )
1178 : {
1179 0 : delete poFeature;
1180 0 : return NULL;
1181 : }
1182 :
1183 : /* -------------------------------------------------------------------- */
1184 : /* Transform the geometry. */
1185 : /* -------------------------------------------------------------------- */
1186 0 : if( poBlock->poGeometry != NULL )
1187 : {
1188 0 : OGRGeometry *poGeometry = poBlock->poGeometry->clone();
1189 :
1190 0 : poGeometry->transform( &oTransformer );
1191 :
1192 0 : poFeature->SetGeometryDirectly( poGeometry );
1193 : }
1194 :
1195 : /* -------------------------------------------------------------------- */
1196 : /* If we have complete features associated with the block, push */
1197 : /* them on the pending feature stack copying over key override */
1198 : /* information. */
1199 : /* */
1200 : /* Note that while we transform the geometry of the features we */
1201 : /* don't adjust subtle things like text angle. */
1202 : /* -------------------------------------------------------------------- */
1203 : unsigned int iSubFeat;
1204 :
1205 0 : for( iSubFeat = 0; iSubFeat < poBlock->apoFeatures.size(); iSubFeat++ )
1206 : {
1207 0 : OGRFeature *poSubFeature = poBlock->apoFeatures[iSubFeat]->Clone();
1208 :
1209 0 : if( poSubFeature->GetGeometryRef() != NULL )
1210 0 : poSubFeature->GetGeometryRef()->transform( &oTransformer );
1211 :
1212 0 : apoPendingFeatures.push( poSubFeature );
1213 : }
1214 :
1215 : /* -------------------------------------------------------------------- */
1216 : /* Return the working feature if we had geometry, otherwise */
1217 : /* return NULL and let the machinery find the rest of the */
1218 : /* features in the pending feature stack. */
1219 : /* -------------------------------------------------------------------- */
1220 0 : if( poBlock->poGeometry == NULL )
1221 : {
1222 0 : delete poFeature;
1223 0 : return NULL;
1224 : }
1225 : else
1226 : {
1227 0 : return poFeature;
1228 0 : }
1229 : }
1230 :
1231 : /************************************************************************/
1232 : /* GetNextUnfilteredFeature() */
1233 : /************************************************************************/
1234 :
1235 23 : OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
1236 :
1237 : {
1238 23 : OGRFeature *poFeature = NULL;
1239 :
1240 : /* -------------------------------------------------------------------- */
1241 : /* If we have pending features, return one of them. */
1242 : /* -------------------------------------------------------------------- */
1243 23 : if( !apoPendingFeatures.empty() )
1244 : {
1245 4 : poFeature = apoPendingFeatures.top();
1246 4 : apoPendingFeatures.pop();
1247 :
1248 4 : poFeature->SetFID( iNextFID++ );
1249 4 : return poFeature;
1250 : }
1251 :
1252 : /* -------------------------------------------------------------------- */
1253 : /* Read the entity type. */
1254 : /* -------------------------------------------------------------------- */
1255 : char szLineBuf[257];
1256 : int nCode;
1257 :
1258 56 : while( poFeature == NULL )
1259 : {
1260 : // read ahead to an entity.
1261 19 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 ) {}
1262 :
1263 19 : if( nCode == -1 )
1264 : {
1265 0 : CPLDebug( "DXF", "Unexpected end of data without ENDSEC." );
1266 0 : return NULL;
1267 : }
1268 :
1269 19 : if( EQUAL(szLineBuf,"ENDSEC") )
1270 : {
1271 : //CPLDebug( "DXF", "Clean end of features at ENDSEC." );
1272 1 : poDS->UnreadValue();
1273 1 : return NULL;
1274 : }
1275 :
1276 18 : if( EQUAL(szLineBuf,"ENDBLK") )
1277 : {
1278 : //CPLDebug( "DXF", "Clean end of block at ENDBLK." );
1279 0 : poDS->UnreadValue();
1280 0 : return NULL;
1281 : }
1282 :
1283 : /* -------------------------------------------------------------------- */
1284 : /* Handle the entity. */
1285 : /* -------------------------------------------------------------------- */
1286 18 : oStyleProperties.clear();
1287 :
1288 18 : if( EQUAL(szLineBuf,"POINT") )
1289 : {
1290 2 : poFeature = TranslatePOINT();
1291 : }
1292 16 : else if( EQUAL(szLineBuf,"MTEXT") )
1293 : {
1294 2 : poFeature = TranslateMTEXT();
1295 : }
1296 14 : else if( EQUAL(szLineBuf,"TEXT") )
1297 : {
1298 0 : poFeature = TranslateTEXT();
1299 : }
1300 14 : else if( EQUAL(szLineBuf,"LINE") )
1301 : {
1302 4 : poFeature = TranslateLINE();
1303 : }
1304 10 : else if( EQUAL(szLineBuf,"POLYLINE") )
1305 : {
1306 0 : poFeature = TranslatePOLYLINE();
1307 : }
1308 10 : else if( EQUAL(szLineBuf,"LWPOLYLINE") )
1309 : {
1310 0 : poFeature = TranslateLWPOLYLINE();
1311 : }
1312 10 : else if( EQUAL(szLineBuf,"CIRCLE") )
1313 : {
1314 0 : poFeature = TranslateCIRCLE();
1315 : }
1316 10 : else if( EQUAL(szLineBuf,"ELLIPSE") )
1317 : {
1318 4 : poFeature = TranslateELLIPSE();
1319 : }
1320 6 : else if( EQUAL(szLineBuf,"ARC") )
1321 : {
1322 2 : poFeature = TranslateARC();
1323 : }
1324 4 : else if( EQUAL(szLineBuf,"SPLINE") )
1325 : {
1326 0 : poFeature = TranslateSPLINE();
1327 : }
1328 4 : else if( EQUAL(szLineBuf,"INSERT") )
1329 : {
1330 0 : poFeature = TranslateINSERT();
1331 : }
1332 4 : else if( EQUAL(szLineBuf,"DIMENSION") )
1333 : {
1334 4 : poFeature = TranslateDIMENSION();
1335 : }
1336 : else
1337 : {
1338 0 : CPLDebug( "DXF", "Ignoring entity '%s'.", szLineBuf );
1339 : }
1340 : }
1341 :
1342 : /* -------------------------------------------------------------------- */
1343 : /* Set FID. */
1344 : /* -------------------------------------------------------------------- */
1345 18 : poFeature->SetFID( iNextFID++ );
1346 18 : m_nFeaturesRead++;
1347 :
1348 18 : return poFeature;
1349 : }
1350 :
1351 : /************************************************************************/
1352 : /* GetNextFeature() */
1353 : /************************************************************************/
1354 :
1355 23 : OGRFeature *OGRDXFLayer::GetNextFeature()
1356 :
1357 : {
1358 0 : while( TRUE )
1359 : {
1360 23 : OGRFeature *poFeature = GetNextUnfilteredFeature();
1361 :
1362 23 : if( poFeature == NULL )
1363 1 : return NULL;
1364 :
1365 22 : if( (m_poFilterGeom == NULL
1366 : || FilterGeometry( poFeature->GetGeometryRef() ) )
1367 : && (m_poAttrQuery == NULL
1368 : || m_poAttrQuery->Evaluate( poFeature ) ) )
1369 : {
1370 22 : return poFeature;
1371 : }
1372 :
1373 0 : delete poFeature;
1374 : }
1375 : }
1376 :
1377 : /************************************************************************/
1378 : /* TestCapability() */
1379 : /************************************************************************/
1380 :
1381 0 : int OGRDXFLayer::TestCapability( const char * pszCap )
1382 :
1383 : {
1384 0 : return FALSE;
1385 : }
1386 :
|