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