1 : /******************************************************************************
2 : * $Id: ogrdxflayer.cpp 19643 2010-05-08 21:56:18Z rouault $
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 : #include "ogrdxf_polyline_smooth.h"
33 :
34 :
35 : CPL_CVSID("$Id: ogrdxflayer.cpp 19643 2010-05-08 21:56:18Z rouault $");
36 :
37 : #ifndef PI
38 : #define PI 3.14159265358979323846
39 : #endif
40 :
41 : /************************************************************************/
42 : /* OGRDXFLayer() */
43 : /************************************************************************/
44 :
45 6 : OGRDXFLayer::OGRDXFLayer( OGRDXFDataSource *poDS )
46 :
47 : {
48 6 : this->poDS = poDS;
49 :
50 6 : iNextFID = 0;
51 :
52 6 : poFeatureDefn = new OGRFeatureDefn( "entities" );
53 6 : poFeatureDefn->Reference();
54 :
55 6 : OGRFieldDefn oLayerField( "Layer", OFTString );
56 6 : poFeatureDefn->AddFieldDefn( &oLayerField );
57 :
58 6 : OGRFieldDefn oClassField( "SubClasses", OFTString );
59 6 : poFeatureDefn->AddFieldDefn( &oClassField );
60 :
61 6 : OGRFieldDefn oExtendedField( "ExtendedEntity", OFTString );
62 6 : poFeatureDefn->AddFieldDefn( &oExtendedField );
63 :
64 6 : OGRFieldDefn oLinetypeField( "Linetype", OFTString );
65 6 : poFeatureDefn->AddFieldDefn( &oLinetypeField );
66 :
67 6 : OGRFieldDefn oEntityHandleField( "EntityHandle", OFTString );
68 6 : poFeatureDefn->AddFieldDefn( &oEntityHandleField );
69 :
70 6 : OGRFieldDefn oTextField( "Text", OFTString );
71 6 : poFeatureDefn->AddFieldDefn( &oTextField );
72 6 : }
73 :
74 : /************************************************************************/
75 : /* ~OGRDXFLayer() */
76 : /************************************************************************/
77 :
78 6 : OGRDXFLayer::~OGRDXFLayer()
79 :
80 : {
81 6 : ClearPendingFeatures();
82 6 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
83 : {
84 : CPLDebug( "DXF", "%d features read on layer '%s'.",
85 : (int) m_nFeaturesRead,
86 6 : poFeatureDefn->GetName() );
87 : }
88 :
89 6 : if( poFeatureDefn )
90 6 : poFeatureDefn->Release();
91 6 : }
92 :
93 : /************************************************************************/
94 : /* ClearPendingFeatures() */
95 : /************************************************************************/
96 :
97 15 : void OGRDXFLayer::ClearPendingFeatures()
98 :
99 : {
100 30 : while( !apoPendingFeatures.empty() )
101 : {
102 0 : delete apoPendingFeatures.top();
103 0 : apoPendingFeatures.pop();
104 : }
105 15 : }
106 :
107 : /************************************************************************/
108 : /* ResetReading() */
109 : /************************************************************************/
110 :
111 9 : void OGRDXFLayer::ResetReading()
112 :
113 : {
114 9 : iNextFID = 0;
115 9 : ClearPendingFeatures();
116 9 : poDS->RestartEntities();
117 9 : }
118 :
119 : /************************************************************************/
120 : /* TranslateGenericProperty() */
121 : /* */
122 : /* Try and convert entity properties handled similarly for most */
123 : /* or all entity types. */
124 : /************************************************************************/
125 :
126 : void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature,
127 230 : int nCode, char *pszValue )
128 :
129 : {
130 230 : switch( nCode )
131 : {
132 : case 8:
133 29 : poFeature->SetField( "Layer", pszValue );
134 29 : break;
135 :
136 : case 100:
137 : {
138 58 : CPLString osSubClass = poFeature->GetFieldAsString("SubClasses");
139 58 : if( osSubClass.size() > 0 )
140 33 : osSubClass += ":";
141 58 : osSubClass += pszValue;
142 58 : poFeature->SetField( "SubClasses", osSubClass.c_str() );
143 : }
144 58 : break;
145 :
146 : case 62:
147 23 : oStyleProperties["Color"] = pszValue;
148 23 : break;
149 :
150 : case 6:
151 23 : poFeature->SetField( "Linetype", pszValue );
152 23 : break;
153 :
154 : case 370:
155 : case 39:
156 23 : oStyleProperties["LineWeight"] = pszValue;
157 23 : break;
158 :
159 : case 5:
160 25 : poFeature->SetField( "EntityHandle", pszValue );
161 25 : break;
162 :
163 : // Extended entity data
164 : case 1000:
165 : case 1002:
166 : case 1004:
167 : case 1005:
168 : case 1040:
169 : case 1041:
170 : case 1070:
171 : case 1071:
172 : {
173 0 : CPLString osAggregate = poFeature->GetFieldAsString("ExtendedEntity");
174 :
175 0 : if( osAggregate.size() > 0 )
176 0 : osAggregate += " ";
177 0 : osAggregate += pszValue;
178 :
179 0 : poFeature->SetField( "ExtendedEntity", osAggregate );
180 : }
181 0 : break;
182 :
183 : // OCS vector.
184 : case 210:
185 1 : oStyleProperties["210_N.dX"] = pszValue;
186 1 : break;
187 :
188 : case 220:
189 1 : oStyleProperties["220_N.dY"] = pszValue;
190 1 : break;
191 :
192 : case 230:
193 1 : oStyleProperties["230_N.dZ"] = pszValue;
194 : break;
195 :
196 :
197 : default:
198 : break;
199 : }
200 230 : }
201 :
202 : /************************************************************************/
203 : /* PrepareLineStyle() */
204 : /* */
205 : /* For now I don't bother trying to translate the dash/dot */
206 : /* linetype into the style string since I'm not aware of any */
207 : /* application that will honour it anyways. */
208 : /************************************************************************/
209 :
210 23 : void OGRDXFLayer::PrepareLineStyle( OGRFeature *poFeature )
211 :
212 : {
213 23 : CPLString osLayer = poFeature->GetFieldAsString("Layer");
214 :
215 : /* -------------------------------------------------------------------- */
216 : /* Work out the color for this feature. */
217 : /* -------------------------------------------------------------------- */
218 23 : int nColor = 256;
219 :
220 23 : if( oStyleProperties.count("Color") > 0 )
221 19 : nColor = atoi(oStyleProperties["Color"]);
222 :
223 : // Use layer color?
224 23 : if( nColor < 1 || nColor > 255 )
225 : {
226 21 : const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
227 21 : if( pszValue != NULL )
228 21 : nColor = atoi(pszValue);
229 : }
230 :
231 23 : if( nColor < 1 || nColor > 255 )
232 5 : return;
233 :
234 : /* -------------------------------------------------------------------- */
235 : /* Get line weight if available. */
236 : /* -------------------------------------------------------------------- */
237 18 : double dfWeight = 0.0;
238 :
239 18 : if( oStyleProperties.count("LineWeight") > 0 )
240 : {
241 16 : CPLString osWeight = oStyleProperties["LineWeight"];
242 :
243 16 : if( osWeight == "-1" )
244 14 : osWeight = poDS->LookupLayerProperty(osLayer,"LineWeight");
245 :
246 16 : dfWeight = CPLAtof(osWeight) / 100.0;
247 : }
248 :
249 : /* -------------------------------------------------------------------- */
250 : /* Format the style string. */
251 : /* -------------------------------------------------------------------- */
252 18 : CPLString osStyle;
253 18 : const unsigned char *pabyDXFColors = OGRDXFDriver::GetDXFColorTable();
254 :
255 : osStyle.Printf( "PEN(c:#%02x%02x%02x",
256 : pabyDXFColors[nColor*3+0],
257 : pabyDXFColors[nColor*3+1],
258 18 : pabyDXFColors[nColor*3+2] );
259 :
260 18 : if( dfWeight > 0.0 )
261 : {
262 : char szBuffer[64];
263 0 : snprintf(szBuffer, sizeof(szBuffer), "%.2g", dfWeight);
264 0 : char* pszComma = strchr(szBuffer, ',');
265 0 : if (pszComma)
266 0 : *pszComma = '.';
267 0 : osStyle += CPLString().Printf( ",w:%smm", szBuffer );
268 : }
269 :
270 18 : osStyle += ")";
271 :
272 18 : poFeature->SetStyleString( osStyle );
273 : }
274 :
275 : /************************************************************************/
276 : /* OCSTransformer */
277 : /************************************************************************/
278 :
279 : class OCSTransformer : public OGRCoordinateTransformation
280 1 : {
281 : private:
282 : double adfN[3];
283 : double adfAX[3];
284 : double adfAY[3];
285 :
286 : public:
287 1 : OCSTransformer( double adfN[3] ) {
288 : static const double dSmall = 1.0 / 64.0;
289 : static const double adfWZ[3] = {0, 0, 1};
290 : static const double adfWY[3] = {0, 1, 0};
291 :
292 1 : memcpy( this->adfN, adfN, sizeof(double)*3 );
293 :
294 1 : if ((ABS(adfN[0]) < dSmall) && (ABS(adfN[1]) < dSmall))
295 0 : CrossProduct(adfWY, adfN, adfAX);
296 : else
297 1 : CrossProduct(adfWZ, adfN, adfAX);
298 :
299 1 : Scale2Unit( adfAX );
300 1 : CrossProduct(adfN, adfAX, adfAY);
301 1 : Scale2Unit( adfAY );
302 1 : }
303 :
304 2 : void CrossProduct(const double *a, const double *b, double *vResult) {
305 2 : vResult[0] = a[1] * b[2] - a[2] * b[1];
306 2 : vResult[1] = a[2] * b[0] - a[0] * b[2];
307 2 : vResult[2] = a[0] * b[1] - a[1] * b[0];
308 2 : }
309 :
310 2 : void Scale2Unit(double* adfV) {
311 2 : double dfLen=sqrt(adfV[0]*adfV[0] + adfV[1]*adfV[1] + adfV[2]*adfV[2]);
312 2 : if (dfLen != 0)
313 : {
314 2 : adfV[0] /= dfLen;
315 2 : adfV[1] /= dfLen;
316 2 : adfV[2] /= dfLen;
317 : }
318 2 : }
319 0 : OGRSpatialReference *GetSourceCS() { return NULL; }
320 1 : OGRSpatialReference *GetTargetCS() { return NULL; }
321 : int Transform( int nCount,
322 1 : double *x, double *y, double *z )
323 1 : { return TransformEx( nCount, x, y, z, NULL ); }
324 :
325 : int TransformEx( int nCount,
326 : double *adfX, double *adfY, double *adfZ = NULL,
327 1 : int *pabSuccess = NULL )
328 : {
329 : int i;
330 4 : for( i = 0; i < nCount; i++ )
331 : {
332 3 : double x = adfX[i], y = adfY[i], z = adfZ[i];
333 :
334 3 : adfX[i] = x * adfAX[0] + y * adfAY[0] + z * adfN[0];
335 3 : adfY[i] = x * adfAX[1] + y * adfAY[1] + z * adfN[1];
336 3 : adfZ[i] = x * adfAX[2] + y * adfAY[2] + z * adfN[2];
337 :
338 3 : if( pabSuccess )
339 0 : pabSuccess[i] = TRUE;
340 : }
341 1 : return TRUE;
342 : }
343 : };
344 :
345 : /************************************************************************/
346 : /* ApplyOCSTransformer() */
347 : /* */
348 : /* Apply a transformation from OCS to world coordinates if an */
349 : /* OCS vector was found in the object. */
350 : /************************************************************************/
351 :
352 6 : void OGRDXFLayer::ApplyOCSTransformer( OGRGeometry *poGeometry )
353 :
354 : {
355 6 : if( oStyleProperties.count("210_N.dX") == 0
356 : || oStyleProperties.count("220_N.dY") == 0
357 : || oStyleProperties.count("230_N.dZ") == 0 )
358 5 : return;
359 :
360 1 : if( poGeometry == NULL )
361 0 : return;
362 :
363 : double adfN[3];
364 :
365 1 : adfN[0] = CPLAtof(oStyleProperties["210_N.dX"]);
366 2 : adfN[1] = CPLAtof(oStyleProperties["220_N.dY"]);
367 2 : adfN[2] = CPLAtof(oStyleProperties["230_N.dZ"]);
368 :
369 1 : OCSTransformer oTransformer( adfN );
370 :
371 2 : poGeometry->transform( &oTransformer );
372 : }
373 :
374 : /************************************************************************/
375 : /* TranslateMTEXT() */
376 : /************************************************************************/
377 :
378 2 : OGRFeature *OGRDXFLayer::TranslateMTEXT()
379 :
380 : {
381 : char szLineBuf[257];
382 : int nCode;
383 2 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
384 2 : double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
385 2 : double dfAngle = 0.0;
386 2 : double dfHeight = 0.0;
387 2 : double dfXDirection = 0.0, dfYDirection = 0.0;
388 2 : int bHaveZ = FALSE;
389 2 : int nAttachmentPoint = -1;
390 2 : CPLString osText;
391 :
392 40 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
393 : {
394 36 : switch( nCode )
395 : {
396 : case 10:
397 2 : dfX = CPLAtof(szLineBuf);
398 2 : break;
399 :
400 : case 20:
401 2 : dfY = CPLAtof(szLineBuf);
402 2 : break;
403 :
404 : case 30:
405 0 : dfZ = CPLAtof(szLineBuf);
406 0 : bHaveZ = TRUE;
407 0 : break;
408 :
409 : case 40:
410 2 : dfHeight = CPLAtof(szLineBuf);
411 2 : break;
412 :
413 : case 71:
414 2 : nAttachmentPoint = atoi(szLineBuf);
415 2 : break;
416 :
417 : case 11:
418 0 : dfXDirection = CPLAtof(szLineBuf);
419 0 : break;
420 :
421 : case 21:
422 0 : dfYDirection = CPLAtof(szLineBuf);
423 0 : dfAngle = atan2( dfYDirection, dfXDirection ) * 180.0 / PI;
424 0 : break;
425 :
426 : case 1:
427 : case 3:
428 2 : osText += szLineBuf;
429 2 : break;
430 :
431 : case 50:
432 2 : dfAngle = CPLAtof(szLineBuf);
433 2 : break;
434 :
435 : default:
436 24 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
437 : break;
438 : }
439 : }
440 :
441 2 : if( nCode == 0 )
442 2 : poDS->UnreadValue();
443 :
444 2 : poFeature->SetField( "Text", osText );
445 :
446 2 : if( bHaveZ )
447 0 : poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY, dfZ ) );
448 : else
449 2 : poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY ) );
450 :
451 : /* -------------------------------------------------------------------- */
452 : /* Work out the color for this feature. */
453 : /* -------------------------------------------------------------------- */
454 2 : int nColor = 256;
455 :
456 2 : if( oStyleProperties.count("Color") > 0 )
457 2 : nColor = atoi(oStyleProperties["Color"]);
458 :
459 : // Use layer color?
460 2 : if( nColor < 1 || nColor > 255 )
461 : {
462 2 : CPLString osLayer = poFeature->GetFieldAsString("Layer");
463 2 : const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
464 2 : if( pszValue != NULL )
465 2 : nColor = atoi(pszValue);
466 : }
467 :
468 : /* -------------------------------------------------------------------- */
469 : /* Prepare style string. */
470 : /* -------------------------------------------------------------------- */
471 2 : CPLString osStyle;
472 : char szBuffer[64];
473 : char* pszComma;
474 :
475 2 : osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\"",osText.c_str());
476 :
477 2 : if( dfAngle != 0.0 )
478 : {
479 2 : snprintf(szBuffer, sizeof(szBuffer), "%.3g", dfAngle);
480 2 : pszComma = strchr(szBuffer, ',');
481 2 : if (pszComma)
482 0 : *pszComma = '.';
483 2 : osStyle += CPLString().Printf(",a:%s", szBuffer);
484 : }
485 :
486 2 : if( dfHeight != 0.0 )
487 : {
488 2 : snprintf(szBuffer, sizeof(szBuffer), "%.3g", dfHeight);
489 2 : pszComma = strchr(szBuffer, ',');
490 2 : if (pszComma)
491 0 : *pszComma = '.';
492 2 : osStyle += CPLString().Printf(",s:%sg", szBuffer);
493 : }
494 :
495 2 : if( nAttachmentPoint >= 0 && nAttachmentPoint <= 9 )
496 : {
497 : const static int anAttachmentMap[10] =
498 : { -1, 7, 8, 9, 4, 5, 6, 1, 2, 3 };
499 :
500 : osStyle +=
501 2 : CPLString().Printf(",p:%d", anAttachmentMap[nAttachmentPoint]);
502 : }
503 :
504 2 : if( nColor > 0 && nColor < 256 )
505 : {
506 2 : const unsigned char *pabyDXFColors = OGRDXFDriver::GetDXFColorTable();
507 : osStyle +=
508 : CPLString().Printf( ",c:#%02x%02x%02x",
509 : pabyDXFColors[nColor*3+0],
510 : pabyDXFColors[nColor*3+1],
511 2 : pabyDXFColors[nColor*3+2] );
512 : }
513 :
514 2 : osStyle += ")";
515 :
516 2 : poFeature->SetStyleString( osStyle );
517 :
518 2 : return poFeature;
519 : }
520 :
521 : /************************************************************************/
522 : /* TranslateTEXT() */
523 : /************************************************************************/
524 :
525 0 : OGRFeature *OGRDXFLayer::TranslateTEXT()
526 :
527 : {
528 : char szLineBuf[257];
529 : int nCode;
530 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
531 0 : double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
532 0 : double dfAngle = 0.0;
533 0 : double dfHeight = 0.0;
534 0 : CPLString osText;
535 0 : int bHaveZ = FALSE;
536 :
537 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
538 : {
539 0 : switch( nCode )
540 : {
541 : case 10:
542 0 : dfX = CPLAtof(szLineBuf);
543 0 : break;
544 :
545 : case 20:
546 0 : dfY = CPLAtof(szLineBuf);
547 0 : break;
548 :
549 : case 30:
550 0 : dfZ = CPLAtof(szLineBuf);
551 0 : bHaveZ = TRUE;
552 0 : break;
553 :
554 : case 40:
555 0 : dfHeight = CPLAtof(szLineBuf);
556 0 : break;
557 :
558 : case 1:
559 : case 3:
560 0 : osText += szLineBuf;
561 0 : break;
562 :
563 : case 50:
564 0 : dfAngle = CPLAtof(szLineBuf);
565 0 : break;
566 :
567 : default:
568 0 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
569 : break;
570 : }
571 : }
572 :
573 0 : if( nCode == 0 )
574 0 : poDS->UnreadValue();
575 :
576 0 : poFeature->SetField( "Text", osText );
577 :
578 0 : if( bHaveZ )
579 0 : poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY, dfZ ) );
580 : else
581 0 : poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY ) );
582 :
583 : /* -------------------------------------------------------------------- */
584 : /* Prepare style string. */
585 : /* -------------------------------------------------------------------- */
586 0 : CPLString osStyle;
587 : char szBuffer[64];
588 : char* pszComma;
589 :
590 0 : osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\"",osText.c_str());
591 :
592 0 : if( dfAngle != 0.0 )
593 : {
594 0 : snprintf(szBuffer, sizeof(szBuffer), "%.3g", dfAngle);
595 0 : pszComma = strchr(szBuffer, ',');
596 0 : if (pszComma)
597 0 : *pszComma = '.';
598 0 : osStyle += CPLString().Printf(",a:%s", szBuffer);
599 : }
600 :
601 0 : if( dfHeight != 0.0 )
602 : {
603 0 : snprintf(szBuffer, sizeof(szBuffer), "%.3g", dfHeight);
604 0 : pszComma = strchr(szBuffer, ',');
605 0 : if (pszComma)
606 0 : *pszComma = '.';
607 0 : osStyle += CPLString().Printf(",s:%sg", szBuffer);
608 : }
609 :
610 : // add color!
611 :
612 0 : osStyle += ")";
613 :
614 0 : poFeature->SetStyleString( osStyle );
615 :
616 0 : return poFeature;
617 : }
618 :
619 : /************************************************************************/
620 : /* TranslatePOINT() */
621 : /************************************************************************/
622 :
623 4 : OGRFeature *OGRDXFLayer::TranslatePOINT()
624 :
625 : {
626 : char szLineBuf[257];
627 : int nCode;
628 4 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
629 4 : double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
630 4 : int bHaveZ = FALSE;
631 :
632 36 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
633 : {
634 28 : switch( nCode )
635 : {
636 : case 10:
637 4 : dfX = CPLAtof(szLineBuf);
638 4 : break;
639 :
640 : case 20:
641 4 : dfY = CPLAtof(szLineBuf);
642 4 : break;
643 :
644 : case 30:
645 4 : dfZ = CPLAtof(szLineBuf);
646 4 : bHaveZ = TRUE;
647 4 : break;
648 :
649 : default:
650 16 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
651 : break;
652 : }
653 : }
654 :
655 4 : if( bHaveZ )
656 4 : poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY, dfZ ) );
657 : else
658 0 : poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY ) );
659 :
660 4 : if( nCode == 0 )
661 4 : poDS->UnreadValue();
662 :
663 4 : return poFeature;
664 : }
665 :
666 : /************************************************************************/
667 : /* TranslateLINE() */
668 : /************************************************************************/
669 :
670 7 : OGRFeature *OGRDXFLayer::TranslateLINE()
671 :
672 : {
673 : char szLineBuf[257];
674 : int nCode;
675 7 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
676 7 : double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0;
677 7 : double dfX2 = 0.0, dfY2 = 0.0, dfZ2 = 0.0;
678 7 : int bHaveZ = FALSE;
679 :
680 : /* -------------------------------------------------------------------- */
681 : /* Process values. */
682 : /* -------------------------------------------------------------------- */
683 108 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
684 : {
685 94 : switch( nCode )
686 : {
687 : case 10:
688 7 : dfX1 = CPLAtof(szLineBuf);
689 7 : break;
690 :
691 : case 11:
692 7 : dfX2 = CPLAtof(szLineBuf);
693 7 : break;
694 :
695 : case 20:
696 7 : dfY1 = CPLAtof(szLineBuf);
697 7 : break;
698 :
699 : case 21:
700 7 : dfY2 = CPLAtof(szLineBuf);
701 7 : break;
702 :
703 : case 30:
704 7 : dfZ1 = CPLAtof(szLineBuf);
705 7 : bHaveZ = TRUE;
706 7 : break;
707 :
708 : case 31:
709 7 : dfZ2 = CPLAtof(szLineBuf);
710 7 : bHaveZ = TRUE;
711 7 : break;
712 :
713 : default:
714 52 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
715 : break;
716 : }
717 : }
718 :
719 7 : if( nCode == 0 )
720 7 : poDS->UnreadValue();
721 :
722 : /* -------------------------------------------------------------------- */
723 : /* Create geometry */
724 : /* -------------------------------------------------------------------- */
725 7 : OGRLineString *poLS = new OGRLineString();
726 7 : if( bHaveZ )
727 : {
728 7 : poLS->addPoint( dfX1, dfY1, dfZ1 );
729 7 : poLS->addPoint( dfX2, dfY2, dfZ2 );
730 : }
731 : else
732 : {
733 0 : poLS->addPoint( dfX1, dfY1 );
734 0 : poLS->addPoint( dfX2, dfY2 );
735 : }
736 :
737 7 : poFeature->SetGeometryDirectly( poLS );
738 :
739 7 : PrepareLineStyle( poFeature );
740 :
741 7 : return poFeature;
742 : }
743 :
744 : /************************************************************************/
745 : /* TranslateLWPOLYLINE() */
746 : /************************************************************************/
747 5 : OGRFeature *OGRDXFLayer::TranslateLWPOLYLINE()
748 :
749 : {
750 : // Collect vertices and attributes into a smooth polyline.
751 : // If there are no bulges, then we are a straight-line polyline.
752 : // Single-vertex polylines become points.
753 : // Group code 30 (vertex Z) is not part of this entity.
754 :
755 : char szLineBuf[257];
756 : int nCode;
757 5 : int nPolylineFlag = 0;
758 :
759 :
760 5 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
761 5 : double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
762 5 : int bHaveX = FALSE;
763 5 : int bHaveY = FALSE;
764 :
765 5 : int nNumVertices = 1; // use 1 based index
766 5 : int npolyarcVertexCount = 1;
767 5 : int bPLineGen = FALSE;
768 5 : double dfBulge = 0.0;
769 5 : DXFSmoothPolyline smoothPolyline;
770 :
771 5 : smoothPolyline.setCoordinateDimension(2);
772 :
773 : /* -------------------------------------------------------------------- */
774 : /* Collect information from the LWPOLYLINE object itself. */
775 : /* -------------------------------------------------------------------- */
776 96 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
777 : {
778 86 : if(npolyarcVertexCount > nNumVertices)
779 : {
780 : CPLError( CE_Failure, CPLE_AppDefined,
781 0 : "Too many vertices found in LWPOLYLINE." );
782 0 : delete poFeature;
783 0 : return NULL;
784 : }
785 :
786 86 : switch( nCode )
787 : {
788 : case 38:
789 : // Constant elevation.
790 1 : dfZ = CPLAtof(szLineBuf);
791 1 : smoothPolyline.setCoordinateDimension(3);
792 1 : break;
793 :
794 : case 90:
795 5 : nNumVertices = atoi(szLineBuf);
796 5 : break;
797 :
798 : case 70:
799 5 : nPolylineFlag = atoi(szLineBuf);
800 5 : break;
801 :
802 : case 10:
803 19 : if( bHaveX && bHaveY )
804 : {
805 14 : smoothPolyline.AddPoint(dfX, dfY, dfZ, dfBulge);
806 14 : npolyarcVertexCount++;
807 14 : dfBulge = 0.0;
808 14 : bHaveY = FALSE;
809 : }
810 19 : dfX = CPLAtof(szLineBuf);
811 19 : bHaveX = TRUE;
812 19 : break;
813 :
814 : case 20:
815 19 : if( bHaveX && bHaveY )
816 : {
817 0 : smoothPolyline.AddPoint( dfX, dfY, dfZ, dfBulge );
818 0 : npolyarcVertexCount++;
819 0 : dfBulge = 0.0;
820 0 : bHaveX = FALSE;
821 : }
822 19 : dfY = CPLAtof(szLineBuf);
823 19 : bHaveY = TRUE;
824 19 : break;
825 :
826 : case 42:
827 4 : dfBulge = CPLAtof(szLineBuf);
828 4 : break;
829 :
830 :
831 : default:
832 33 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
833 : break;
834 : }
835 : }
836 :
837 5 : poDS->UnreadValue();
838 :
839 5 : if( bHaveX && bHaveY )
840 5 : smoothPolyline.AddPoint(dfX, dfY, dfZ, dfBulge);
841 :
842 :
843 5 : if(smoothPolyline.IsEmpty())
844 : {
845 0 : delete poFeature;
846 0 : return NULL;
847 : }
848 :
849 : /* -------------------------------------------------------------------- */
850 : /* Close polyline if necessary. */
851 : /* -------------------------------------------------------------------- */
852 5 : if(nPolylineFlag & 0x01)
853 2 : smoothPolyline.Close();
854 :
855 5 : OGRGeometry* poGeom = smoothPolyline.Tesselate();
856 5 : ApplyOCSTransformer( poGeom );
857 5 : poFeature->SetGeometryDirectly( poGeom );
858 :
859 5 : PrepareLineStyle( poFeature );
860 :
861 5 : return poFeature;
862 : }
863 :
864 :
865 : /************************************************************************/
866 : /* TranslatePOLYLINE() */
867 : /* */
868 : /* We also capture the following VERTEXes. */
869 : /************************************************************************/
870 :
871 1 : OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
872 :
873 : {
874 : char szLineBuf[257];
875 : int nCode;
876 1 : int nPolylineFlag = 0;
877 1 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
878 :
879 : /* -------------------------------------------------------------------- */
880 : /* Collect information from the POLYLINE object itself. */
881 : /* -------------------------------------------------------------------- */
882 8 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
883 : {
884 6 : switch( nCode )
885 : {
886 : case 70:
887 1 : nPolylineFlag = atoi(szLineBuf);
888 1 : break;
889 :
890 : default:
891 5 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
892 : break;
893 : }
894 : }
895 :
896 : /* -------------------------------------------------------------------- */
897 : /* Collect VERTEXes as a smooth polyline. */
898 : /* -------------------------------------------------------------------- */
899 1 : double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
900 1 : double dfBulge = 0.0;
901 1 : DXFSmoothPolyline smoothPolyline;
902 :
903 1 : smoothPolyline.setCoordinateDimension(2);
904 :
905 7 : while( nCode == 0 && !EQUAL(szLineBuf,"SEQEND") )
906 : {
907 : // Eat non-vertex objects.
908 5 : if( !EQUAL(szLineBuf,"VERTEX") )
909 : {
910 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf)))>0 ) {}
911 0 : continue;
912 : }
913 :
914 : // process a Vertex
915 39 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
916 : {
917 29 : switch( nCode )
918 : {
919 : case 10:
920 5 : dfX = CPLAtof(szLineBuf);
921 5 : break;
922 :
923 : case 20:
924 5 : dfY = CPLAtof(szLineBuf);
925 5 : break;
926 :
927 : case 30:
928 5 : dfZ = CPLAtof(szLineBuf);
929 5 : smoothPolyline.setCoordinateDimension(3);
930 5 : break;
931 :
932 : case 42:
933 4 : dfBulge = CPLAtof(szLineBuf);
934 : break;
935 :
936 : default:
937 : break;
938 : }
939 : }
940 :
941 5 : smoothPolyline.AddPoint( dfX, dfY, dfZ, dfBulge );
942 5 : dfBulge = 0.0;
943 : }
944 :
945 : /* -------------------------------------------------------------------- */
946 : /* Close polyline if necessary. */
947 : /* -------------------------------------------------------------------- */
948 1 : if(nPolylineFlag & 0x01)
949 1 : smoothPolyline.Close();
950 :
951 1 : OGRGeometry* poGeom = smoothPolyline.Tesselate();
952 1 : ApplyOCSTransformer( poGeom );
953 1 : poFeature->SetGeometryDirectly( poGeom );
954 :
955 1 : PrepareLineStyle( poFeature );
956 :
957 1 : return poFeature;
958 : }
959 :
960 : /************************************************************************/
961 : /* TranslateCIRCLE() */
962 : /************************************************************************/
963 :
964 0 : OGRFeature *OGRDXFLayer::TranslateCIRCLE()
965 :
966 : {
967 : char szLineBuf[257];
968 : int nCode;
969 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
970 0 : double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0, dfRadius = 0.0;
971 0 : int bHaveZ = FALSE;
972 :
973 : /* -------------------------------------------------------------------- */
974 : /* Process values. */
975 : /* -------------------------------------------------------------------- */
976 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
977 : {
978 0 : switch( nCode )
979 : {
980 : case 10:
981 0 : dfX1 = CPLAtof(szLineBuf);
982 0 : break;
983 :
984 : case 20:
985 0 : dfY1 = CPLAtof(szLineBuf);
986 0 : break;
987 :
988 : case 30:
989 0 : dfZ1 = CPLAtof(szLineBuf);
990 0 : bHaveZ = TRUE;
991 0 : break;
992 :
993 : case 40:
994 0 : dfRadius = CPLAtof(szLineBuf);
995 0 : break;
996 :
997 : default:
998 0 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
999 : break;
1000 : }
1001 : }
1002 :
1003 0 : if( nCode == 0 )
1004 0 : poDS->UnreadValue();
1005 :
1006 : /* -------------------------------------------------------------------- */
1007 : /* Create geometry */
1008 : /* -------------------------------------------------------------------- */
1009 : OGRGeometry *poCircle =
1010 : OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1,
1011 : dfRadius, dfRadius, 0.0,
1012 : 0.0, 360.0,
1013 0 : 0.0 );
1014 :
1015 0 : if( !bHaveZ )
1016 0 : poCircle->flattenTo2D();
1017 :
1018 0 : poFeature->SetGeometryDirectly( poCircle );
1019 0 : PrepareLineStyle( poFeature );
1020 :
1021 0 : return poFeature;
1022 : }
1023 :
1024 : /************************************************************************/
1025 : /* TranslateELLIPSE() */
1026 : /************************************************************************/
1027 :
1028 4 : OGRFeature *OGRDXFLayer::TranslateELLIPSE()
1029 :
1030 : {
1031 : char szLineBuf[257];
1032 : int nCode;
1033 4 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
1034 4 : double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0, dfRatio = 0.0;
1035 4 : double dfStartAngle = 0.0, dfEndAngle = 360.0;
1036 4 : double dfAxisX=0.0, dfAxisY=0.0, dfAxisZ=0.0;
1037 4 : int bHaveZ = FALSE;
1038 :
1039 : /* -------------------------------------------------------------------- */
1040 : /* Process values. */
1041 : /* -------------------------------------------------------------------- */
1042 72 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
1043 : {
1044 64 : switch( nCode )
1045 : {
1046 : case 10:
1047 4 : dfX1 = CPLAtof(szLineBuf);
1048 4 : break;
1049 :
1050 : case 20:
1051 4 : dfY1 = CPLAtof(szLineBuf);
1052 4 : break;
1053 :
1054 : case 30:
1055 4 : dfZ1 = CPLAtof(szLineBuf);
1056 4 : bHaveZ = TRUE;
1057 4 : break;
1058 :
1059 : case 11:
1060 4 : dfAxisX = CPLAtof(szLineBuf);
1061 4 : break;
1062 :
1063 : case 21:
1064 4 : dfAxisY = CPLAtof(szLineBuf);
1065 4 : break;
1066 :
1067 : case 31:
1068 4 : dfAxisZ = CPLAtof(szLineBuf);
1069 4 : break;
1070 :
1071 : case 40:
1072 4 : dfRatio = CPLAtof(szLineBuf);
1073 4 : break;
1074 :
1075 : case 41:
1076 4 : dfEndAngle = -1 * CPLAtof(szLineBuf) * 180.0 / PI;
1077 4 : break;
1078 :
1079 : case 42:
1080 4 : dfStartAngle = -1 * CPLAtof(szLineBuf) * 180.0 / PI;
1081 4 : break;
1082 :
1083 : default:
1084 28 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
1085 : break;
1086 : }
1087 : }
1088 :
1089 4 : if( nCode == 0 )
1090 4 : poDS->UnreadValue();
1091 :
1092 : /* -------------------------------------------------------------------- */
1093 : /* Compute primary and secondary axis lengths, and the angle of */
1094 : /* rotation for the ellipse. */
1095 : /* -------------------------------------------------------------------- */
1096 : double dfPrimaryRadius, dfSecondaryRadius;
1097 : double dfRotation;
1098 :
1099 4 : if( dfStartAngle > dfEndAngle )
1100 0 : dfEndAngle += 360.0;
1101 :
1102 : dfPrimaryRadius = sqrt( dfAxisX * dfAxisX
1103 : + dfAxisY * dfAxisY
1104 4 : + dfAxisZ * dfAxisZ );
1105 :
1106 4 : dfSecondaryRadius = dfRatio * dfPrimaryRadius;
1107 :
1108 4 : dfRotation = -1 * atan2( dfAxisY, dfAxisX ) * 180 / PI;
1109 :
1110 : /* -------------------------------------------------------------------- */
1111 : /* Create geometry */
1112 : /* -------------------------------------------------------------------- */
1113 : OGRGeometry *poEllipse =
1114 : OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1,
1115 : dfPrimaryRadius,
1116 : dfSecondaryRadius,
1117 : dfRotation,
1118 : dfStartAngle, dfEndAngle,
1119 4 : 0.0 );
1120 :
1121 4 : if( !bHaveZ )
1122 0 : poEllipse->flattenTo2D();
1123 :
1124 4 : poFeature->SetGeometryDirectly( poEllipse );
1125 :
1126 4 : PrepareLineStyle( poFeature );
1127 :
1128 4 : return poFeature;
1129 : }
1130 :
1131 : /************************************************************************/
1132 : /* TranslateARC() */
1133 : /************************************************************************/
1134 :
1135 2 : OGRFeature *OGRDXFLayer::TranslateARC()
1136 :
1137 : {
1138 : char szLineBuf[257];
1139 : int nCode;
1140 2 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
1141 2 : double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0, dfRadius = 0.0;
1142 2 : double dfStartAngle = 0.0, dfEndAngle = 360.0;
1143 2 : int bHaveZ = FALSE;
1144 :
1145 : /* -------------------------------------------------------------------- */
1146 : /* Process values. */
1147 : /* -------------------------------------------------------------------- */
1148 32 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
1149 : {
1150 28 : switch( nCode )
1151 : {
1152 : case 10:
1153 2 : dfX1 = CPLAtof(szLineBuf);
1154 2 : break;
1155 :
1156 : case 20:
1157 2 : dfY1 = CPLAtof(szLineBuf);
1158 2 : break;
1159 :
1160 : case 30:
1161 2 : dfZ1 = CPLAtof(szLineBuf);
1162 2 : bHaveZ = TRUE;
1163 2 : break;
1164 :
1165 : case 40:
1166 2 : dfRadius = CPLAtof(szLineBuf);
1167 2 : break;
1168 :
1169 : case 50:
1170 2 : dfEndAngle = -1 * CPLAtof(szLineBuf);
1171 2 : break;
1172 :
1173 : case 51:
1174 2 : dfStartAngle = -1 * CPLAtof(szLineBuf);
1175 2 : break;
1176 :
1177 : default:
1178 16 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
1179 : break;
1180 : }
1181 : }
1182 :
1183 2 : if( nCode == 0 )
1184 2 : poDS->UnreadValue();
1185 :
1186 : /* -------------------------------------------------------------------- */
1187 : /* Create geometry */
1188 : /* -------------------------------------------------------------------- */
1189 2 : if( dfStartAngle > dfEndAngle )
1190 2 : dfEndAngle += 360.0;
1191 :
1192 : OGRGeometry *poArc =
1193 : OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1,
1194 : dfRadius, dfRadius, 0.0,
1195 : dfStartAngle, dfEndAngle,
1196 2 : 0.0 );
1197 2 : if( !bHaveZ )
1198 0 : poArc->flattenTo2D();
1199 :
1200 2 : poFeature->SetGeometryDirectly( poArc );
1201 :
1202 2 : PrepareLineStyle( poFeature );
1203 :
1204 2 : return poFeature;
1205 : }
1206 :
1207 : /************************************************************************/
1208 : /* TranslateSPLINE() */
1209 : /************************************************************************/
1210 :
1211 : void rbspline(int npts,int k,int p1,double b[],double h[], double p[]);
1212 : void rbsplinu(int npts,int k,int p1,double b[],double h[], double p[]);
1213 :
1214 0 : OGRFeature *OGRDXFLayer::TranslateSPLINE()
1215 :
1216 : {
1217 : char szLineBuf[257];
1218 0 : int nCode, nDegree = -1, nFlags = -1, bClosed = FALSE, i;
1219 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
1220 0 : std::vector<double> adfControlPoints;
1221 :
1222 0 : adfControlPoints.push_back(0.0);
1223 :
1224 : /* -------------------------------------------------------------------- */
1225 : /* Process values. */
1226 : /* -------------------------------------------------------------------- */
1227 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
1228 : {
1229 0 : switch( nCode )
1230 : {
1231 : case 10:
1232 0 : adfControlPoints.push_back( CPLAtof(szLineBuf) );
1233 0 : break;
1234 :
1235 : case 20:
1236 0 : adfControlPoints.push_back( CPLAtof(szLineBuf) );
1237 0 : adfControlPoints.push_back( 0.0 );
1238 0 : break;
1239 :
1240 : case 70:
1241 0 : nFlags = atoi(szLineBuf);
1242 0 : if( nFlags & 1 )
1243 0 : bClosed = TRUE;
1244 0 : break;
1245 :
1246 : case 71:
1247 0 : nDegree = atoi(szLineBuf);
1248 0 : break;
1249 :
1250 : default:
1251 0 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
1252 : break;
1253 : }
1254 : }
1255 :
1256 0 : if( nCode == 0 )
1257 0 : poDS->UnreadValue();
1258 :
1259 0 : if( bClosed )
1260 : {
1261 0 : for( i = 0; i < nDegree; i++ )
1262 : {
1263 0 : adfControlPoints.push_back( adfControlPoints[i*3+1] );
1264 0 : adfControlPoints.push_back( adfControlPoints[i*3+2] );
1265 0 : adfControlPoints.push_back( adfControlPoints[i*3+3] );
1266 : }
1267 : }
1268 :
1269 : /* -------------------------------------------------------------------- */
1270 : /* Interpolate spline */
1271 : /* -------------------------------------------------------------------- */
1272 0 : int nControlPoints = adfControlPoints.size() / 3;
1273 0 : std::vector<double> h, p;
1274 :
1275 0 : h.push_back(1.0);
1276 0 : for( i = 0; i < nControlPoints; i++ )
1277 0 : h.push_back( 1.0 );
1278 :
1279 : // resolution:
1280 : //int p1 = getGraphicVariableInt("$SPLINESEGS", 8) * npts;
1281 0 : int p1 = nControlPoints * 8;
1282 :
1283 0 : p.push_back( 0.0 );
1284 0 : for( i = 0; i < 3*p1; i++ )
1285 0 : p.push_back( 0.0 );
1286 :
1287 0 : if( bClosed )
1288 : rbsplinu( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]),
1289 0 : &(h[0]), &(p[0]) );
1290 : else
1291 : rbspline( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]),
1292 0 : &(h[0]), &(p[0]) );
1293 :
1294 : /* -------------------------------------------------------------------- */
1295 : /* Turn into OGR geometry. */
1296 : /* -------------------------------------------------------------------- */
1297 0 : OGRLineString *poLS = new OGRLineString();
1298 :
1299 0 : poLS->setNumPoints( p1 );
1300 0 : for( i = 0; i < p1; i++ )
1301 0 : poLS->setPoint( i, p[i*3+1], p[i*3+2] );
1302 :
1303 0 : poFeature->SetGeometryDirectly( poLS );
1304 :
1305 0 : PrepareLineStyle( poFeature );
1306 :
1307 0 : return poFeature;
1308 : }
1309 :
1310 : /************************************************************************/
1311 : /* GeometryInsertTransformer */
1312 : /************************************************************************/
1313 :
1314 : class GeometryInsertTransformer : public OGRCoordinateTransformation
1315 0 : {
1316 : public:
1317 0 : GeometryInsertTransformer() :
1318 : dfXOffset(0),dfYOffset(0),dfZOffset(0),
1319 : dfXScale(1.0),dfYScale(1.0),dfZScale(1.0),
1320 0 : dfAngle(0.0) {}
1321 :
1322 : double dfXOffset;
1323 : double dfYOffset;
1324 : double dfZOffset;
1325 : double dfXScale;
1326 : double dfYScale;
1327 : double dfZScale;
1328 : double dfAngle;
1329 :
1330 0 : OGRSpatialReference *GetSourceCS() { return NULL; }
1331 0 : OGRSpatialReference *GetTargetCS() { return NULL; }
1332 : int Transform( int nCount,
1333 0 : double *x, double *y, double *z )
1334 0 : { return TransformEx( nCount, x, y, z, NULL ); }
1335 :
1336 : int TransformEx( int nCount,
1337 : double *x, double *y, double *z = NULL,
1338 0 : int *pabSuccess = NULL )
1339 : {
1340 : int i;
1341 0 : for( i = 0; i < nCount; i++ )
1342 : {
1343 : double dfXNew, dfYNew;
1344 :
1345 0 : x[i] *= dfXScale;
1346 0 : y[i] *= dfYScale;
1347 0 : z[i] *= dfZScale;
1348 :
1349 0 : dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
1350 0 : dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
1351 :
1352 0 : x[i] = dfXNew;
1353 0 : y[i] = dfYNew;
1354 :
1355 0 : x[i] += dfXOffset;
1356 0 : y[i] += dfYOffset;
1357 0 : z[i] += dfZOffset;
1358 :
1359 0 : if( pabSuccess )
1360 0 : pabSuccess[i] = TRUE;
1361 : }
1362 0 : return TRUE;
1363 : }
1364 : };
1365 :
1366 : /************************************************************************/
1367 : /* TranslateINSERT() */
1368 : /************************************************************************/
1369 :
1370 0 : OGRFeature *OGRDXFLayer::TranslateINSERT()
1371 :
1372 : {
1373 : char szLineBuf[257];
1374 : int nCode;
1375 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
1376 0 : GeometryInsertTransformer oTransformer;
1377 0 : CPLString osBlockName;
1378 :
1379 : /* -------------------------------------------------------------------- */
1380 : /* Process values. */
1381 : /* -------------------------------------------------------------------- */
1382 0 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
1383 : {
1384 0 : switch( nCode )
1385 : {
1386 : case 10:
1387 0 : oTransformer.dfXOffset = CPLAtof(szLineBuf);
1388 0 : break;
1389 :
1390 : case 20:
1391 0 : oTransformer.dfYOffset = CPLAtof(szLineBuf);
1392 0 : break;
1393 :
1394 : case 30:
1395 0 : oTransformer.dfZOffset = CPLAtof(szLineBuf);
1396 0 : break;
1397 :
1398 : case 41:
1399 0 : oTransformer.dfXScale = CPLAtof(szLineBuf);
1400 0 : break;
1401 :
1402 : case 42:
1403 0 : oTransformer.dfYScale = CPLAtof(szLineBuf);
1404 0 : break;
1405 :
1406 : case 43:
1407 0 : oTransformer.dfZScale = CPLAtof(szLineBuf);
1408 0 : break;
1409 :
1410 : case 50:
1411 0 : oTransformer.dfAngle = CPLAtof(szLineBuf) * PI / 180.0;
1412 0 : break;
1413 :
1414 : case 2:
1415 0 : osBlockName = szLineBuf;
1416 0 : break;
1417 :
1418 : default:
1419 0 : TranslateGenericProperty( poFeature, nCode, szLineBuf );
1420 : break;
1421 : }
1422 : }
1423 :
1424 0 : if( nCode == 0 )
1425 0 : poDS->UnreadValue();
1426 :
1427 : /* -------------------------------------------------------------------- */
1428 : /* Lookup the block. */
1429 : /* -------------------------------------------------------------------- */
1430 0 : DXFBlockDefinition *poBlock = poDS->LookupBlock( osBlockName );
1431 :
1432 0 : if( poBlock == NULL )
1433 : {
1434 0 : delete poFeature;
1435 0 : return NULL;
1436 : }
1437 :
1438 : /* -------------------------------------------------------------------- */
1439 : /* Transform the geometry. */
1440 : /* -------------------------------------------------------------------- */
1441 0 : if( poBlock->poGeometry != NULL )
1442 : {
1443 0 : OGRGeometry *poGeometry = poBlock->poGeometry->clone();
1444 :
1445 0 : poGeometry->transform( &oTransformer );
1446 :
1447 0 : poFeature->SetGeometryDirectly( poGeometry );
1448 : }
1449 :
1450 : /* -------------------------------------------------------------------- */
1451 : /* If we have complete features associated with the block, push */
1452 : /* them on the pending feature stack copying over key override */
1453 : /* information. */
1454 : /* */
1455 : /* Note that while we transform the geometry of the features we */
1456 : /* don't adjust subtle things like text angle. */
1457 : /* -------------------------------------------------------------------- */
1458 : unsigned int iSubFeat;
1459 :
1460 0 : for( iSubFeat = 0; iSubFeat < poBlock->apoFeatures.size(); iSubFeat++ )
1461 : {
1462 0 : OGRFeature *poSubFeature = poBlock->apoFeatures[iSubFeat]->Clone();
1463 :
1464 0 : if( poSubFeature->GetGeometryRef() != NULL )
1465 0 : poSubFeature->GetGeometryRef()->transform( &oTransformer );
1466 :
1467 0 : apoPendingFeatures.push( poSubFeature );
1468 : }
1469 :
1470 : /* -------------------------------------------------------------------- */
1471 : /* Return the working feature if we had geometry, otherwise */
1472 : /* return NULL and let the machinery find the rest of the */
1473 : /* features in the pending feature stack. */
1474 : /* -------------------------------------------------------------------- */
1475 0 : if( poBlock->poGeometry == NULL )
1476 : {
1477 0 : delete poFeature;
1478 0 : return NULL;
1479 : }
1480 : else
1481 : {
1482 0 : return poFeature;
1483 0 : }
1484 : }
1485 :
1486 : /************************************************************************/
1487 : /* GetNextUnfilteredFeature() */
1488 : /************************************************************************/
1489 :
1490 35 : OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
1491 :
1492 : {
1493 35 : OGRFeature *poFeature = NULL;
1494 :
1495 : /* -------------------------------------------------------------------- */
1496 : /* If we have pending features, return one of them. */
1497 : /* -------------------------------------------------------------------- */
1498 35 : if( !apoPendingFeatures.empty() )
1499 : {
1500 4 : poFeature = apoPendingFeatures.top();
1501 4 : apoPendingFeatures.pop();
1502 :
1503 4 : poFeature->SetFID( iNextFID++ );
1504 4 : return poFeature;
1505 : }
1506 :
1507 : /* -------------------------------------------------------------------- */
1508 : /* Read the entity type. */
1509 : /* -------------------------------------------------------------------- */
1510 : char szLineBuf[257];
1511 : int nCode;
1512 :
1513 91 : while( poFeature == NULL )
1514 : {
1515 : // read ahead to an entity.
1516 31 : while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 ) {}
1517 :
1518 31 : if( nCode == -1 )
1519 : {
1520 0 : CPLDebug( "DXF", "Unexpected end of data without ENDSEC." );
1521 0 : return NULL;
1522 : }
1523 :
1524 31 : if( EQUAL(szLineBuf,"ENDSEC") )
1525 : {
1526 : //CPLDebug( "DXF", "Clean end of features at ENDSEC." );
1527 1 : poDS->UnreadValue();
1528 1 : return NULL;
1529 : }
1530 :
1531 30 : if( EQUAL(szLineBuf,"ENDBLK") )
1532 : {
1533 : //CPLDebug( "DXF", "Clean end of block at ENDBLK." );
1534 1 : poDS->UnreadValue();
1535 1 : return NULL;
1536 : }
1537 :
1538 : /* -------------------------------------------------------------------- */
1539 : /* Handle the entity. */
1540 : /* -------------------------------------------------------------------- */
1541 29 : oStyleProperties.clear();
1542 :
1543 29 : if( EQUAL(szLineBuf,"POINT") )
1544 : {
1545 4 : poFeature = TranslatePOINT();
1546 : }
1547 25 : else if( EQUAL(szLineBuf,"MTEXT") )
1548 : {
1549 2 : poFeature = TranslateMTEXT();
1550 : }
1551 23 : else if( EQUAL(szLineBuf,"TEXT") )
1552 : {
1553 0 : poFeature = TranslateTEXT();
1554 : }
1555 23 : else if( EQUAL(szLineBuf,"LINE") )
1556 : {
1557 7 : poFeature = TranslateLINE();
1558 : }
1559 16 : else if( EQUAL(szLineBuf,"POLYLINE") )
1560 : {
1561 1 : poFeature = TranslatePOLYLINE();
1562 : }
1563 15 : else if( EQUAL(szLineBuf,"LWPOLYLINE") )
1564 : {
1565 5 : poFeature = TranslateLWPOLYLINE();
1566 : }
1567 10 : else if( EQUAL(szLineBuf,"CIRCLE") )
1568 : {
1569 0 : poFeature = TranslateCIRCLE();
1570 : }
1571 10 : else if( EQUAL(szLineBuf,"ELLIPSE") )
1572 : {
1573 4 : poFeature = TranslateELLIPSE();
1574 : }
1575 6 : else if( EQUAL(szLineBuf,"ARC") )
1576 : {
1577 2 : poFeature = TranslateARC();
1578 : }
1579 4 : else if( EQUAL(szLineBuf,"SPLINE") )
1580 : {
1581 0 : poFeature = TranslateSPLINE();
1582 : }
1583 4 : else if( EQUAL(szLineBuf,"INSERT") )
1584 : {
1585 0 : poFeature = TranslateINSERT();
1586 : }
1587 4 : else if( EQUAL(szLineBuf,"DIMENSION") )
1588 : {
1589 4 : poFeature = TranslateDIMENSION();
1590 : }
1591 : else
1592 : {
1593 0 : CPLDebug( "DXF", "Ignoring entity '%s'.", szLineBuf );
1594 : }
1595 : }
1596 :
1597 : /* -------------------------------------------------------------------- */
1598 : /* Set FID. */
1599 : /* -------------------------------------------------------------------- */
1600 29 : poFeature->SetFID( iNextFID++ );
1601 29 : m_nFeaturesRead++;
1602 :
1603 29 : return poFeature;
1604 : }
1605 :
1606 : /************************************************************************/
1607 : /* GetNextFeature() */
1608 : /************************************************************************/
1609 :
1610 31 : OGRFeature *OGRDXFLayer::GetNextFeature()
1611 :
1612 : {
1613 0 : while( TRUE )
1614 : {
1615 31 : OGRFeature *poFeature = GetNextUnfilteredFeature();
1616 :
1617 31 : if( poFeature == NULL )
1618 1 : return NULL;
1619 :
1620 30 : if( (m_poFilterGeom == NULL
1621 : || FilterGeometry( poFeature->GetGeometryRef() ) )
1622 : && (m_poAttrQuery == NULL
1623 : || m_poAttrQuery->Evaluate( poFeature ) ) )
1624 : {
1625 30 : return poFeature;
1626 : }
1627 :
1628 0 : delete poFeature;
1629 : }
1630 : }
1631 :
1632 : /************************************************************************/
1633 : /* TestCapability() */
1634 : /************************************************************************/
1635 :
1636 0 : int OGRDXFLayer::TestCapability( const char * pszCap )
1637 :
1638 : {
1639 0 : return FALSE;
1640 : }
1641 :
|