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