OGRErr OGRDXFWriterLayer::WritePOINT( OGRFeature *poFeature ) { WriteValue( 0, "POINT" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbPoint" ); // Write style pen color OGRStyleTool *poTool = nullptr; OGRStyleMgr oSM; if( poFeature->GetStyleString() != nullptr ) { oSM.InitFromFeature( poFeature ); if( oSM.GetPartCount() > 0 ) poTool = oSM.GetPart(0); } if( poTool && poTool->GetType() == OGRSTCPen ) { OGRStylePen *poPen = (OGRStylePen *) poTool; GBool bDefault; if( poPen->Color(bDefault) != nullptr && !bDefault ) WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) ); } delete poTool; OGRPoint *poPoint = poFeature->GetGeometryRef()->toPoint(); WriteValue( 10, poPoint->getX() ); if( !WriteValue( 20, poPoint->getY() ) ) return OGRERR_FAILURE; if( poPoint->getGeometryType() == wkbPoint25D ) { if( !WriteValue( 30, poPoint->getZ() ) ) return OGRERR_FAILURE; } return OGRERR_NONE; }
OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature, const OGRGeometry *poGeom ) { /* -------------------------------------------------------------------- */ /* For now we handle multilinestrings by writing a series of */ /* entities. */ /* -------------------------------------------------------------------- */ if( poGeom == nullptr ) poGeom = poFeature->GetGeometryRef(); if ( poGeom->IsEmpty() ) { return OGRERR_NONE; } if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon || wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString ) { const OGRGeometryCollection *poGC = poGeom->toGeometryCollection(); OGRErr eErr = OGRERR_NONE; for( auto&& poMember: *poGC ) { eErr = WritePOLYLINE( poFeature, poMember ); if( eErr != OGRERR_NONE ) break; } return eErr; } /* -------------------------------------------------------------------- */ /* Polygons are written with on entity per ring. */ /* -------------------------------------------------------------------- */ if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon || wkbFlatten(poGeom->getGeometryType()) == wkbTriangle) { const OGRPolygon *poPoly = poGeom->toPolygon(); OGRErr eErr = OGRERR_NONE; for( auto&& poRing: *poPoly ) { eErr = WritePOLYLINE( poFeature, poRing ); if( eErr != OGRERR_NONE ) break; } return eErr; } /* -------------------------------------------------------------------- */ /* Do we now have a geometry we can work with? */ /* -------------------------------------------------------------------- */ if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString ) return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; const OGRLineString *poLS = poGeom->toLineString(); /* -------------------------------------------------------------------- */ /* Write as a lightweight polygon, */ /* or as POLYLINE if the line contains different heights */ /* -------------------------------------------------------------------- */ int bHasDifferentZ = FALSE; if( poLS->getGeometryType() == wkbLineString25D ) { double z0 = poLS->getZ(0); for( int iVert = 0; iVert < poLS->getNumPoints(); iVert++ ) { if (z0 != poLS->getZ(iVert)) { bHasDifferentZ = TRUE; break; } } } WriteValue( 0, bHasDifferentZ ? "POLYLINE" : "LWPOLYLINE" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); if( bHasDifferentZ ) { WriteValue( 100, "AcDb3dPolyline" ); WriteValue( 10, 0.0 ); WriteValue( 20, 0.0 ); WriteValue( 30, 0.0 ); } else WriteValue( 100, "AcDbPolyline" ); if( EQUAL( poGeom->getGeometryName(), "LINEARRING" ) ) WriteValue( 70, 1 + (bHasDifferentZ ? 8 : 0) ); else WriteValue( 70, 0 + (bHasDifferentZ ? 8 : 0) ); if( !bHasDifferentZ ) WriteValue( 90, poLS->getNumPoints() ); else WriteValue( 66, "1" ); // Vertex Flag /* -------------------------------------------------------------------- */ /* Do we have styling information? */ /* -------------------------------------------------------------------- */ OGRStyleTool *poTool = nullptr; OGRStyleMgr oSM; if( poFeature->GetStyleString() != nullptr ) { oSM.InitFromFeature( poFeature ); if( oSM.GetPartCount() > 0 ) poTool = oSM.GetPart(0); } /* -------------------------------------------------------------------- */ /* Handle a PEN tool to control drawing color and width. */ /* Perhaps one day also dottedness, etc. */ /* -------------------------------------------------------------------- */ if( poTool && poTool->GetType() == OGRSTCPen ) { OGRStylePen *poPen = (OGRStylePen *) poTool; GBool bDefault; if( poPen->Color(bDefault) != nullptr && !bDefault ) WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) ); // we want to fetch the width in ground units. poPen->SetUnit( OGRSTUGround, 1.0 ); const double dfWidth = poPen->Width(bDefault); if( !bDefault ) WriteValue( 370, (int) floor(dfWidth * 100 + 0.5) ); } /* -------------------------------------------------------------------- */ /* Do we have a Linetype for the feature? */ /* -------------------------------------------------------------------- */ CPLString osLineType = poFeature->GetFieldAsString( "Linetype" ); double dfLineTypeScale = 0.0; bool bGotLinetype = false; if( !osLineType.empty() ) { std::vector<double> adfLineType = poDS->oHeaderDS.LookupLineType( osLineType ); if( adfLineType.empty() && oNewLineTypes.count(osLineType) > 0 ) adfLineType = oNewLineTypes[osLineType]; if( !adfLineType.empty() ) { bGotLinetype = true; WriteValue( 6, osLineType ); // If the given linetype is proportional to the linetype data // in the style string, then apply a linetype scale if( poTool != nullptr && poTool->GetType() == OGRSTCPen ) { std::vector<double> adfDefinition = PrepareLineTypeDefinition( static_cast<OGRStylePen *>( poTool ) ); if( !adfDefinition.empty() ) { dfLineTypeScale = IsLineTypeProportional( adfLineType, adfDefinition ); if( dfLineTypeScale != 0.0 && fabs( dfLineTypeScale - 1.0 ) > 1e-4 ) { WriteValue( 48, dfLineTypeScale ); } } } } } if( !bGotLinetype && poTool != nullptr && poTool->GetType() == OGRSTCPen ) { std::vector<double> adfDefinition = PrepareLineTypeDefinition( static_cast<OGRStylePen *>( poTool ) ); if( !adfDefinition.empty() ) { // Is this definition already created and named? for( const auto& oPair : poDS->oHeaderDS.GetLineTypeTable() ) { dfLineTypeScale = IsLineTypeProportional( oPair.second, adfDefinition ); if( dfLineTypeScale != 0.0 ) { osLineType = oPair.first; break; } } if( dfLineTypeScale == 0.0 ) { for( const auto& oPair : oNewLineTypes ) { dfLineTypeScale = IsLineTypeProportional( oPair.second, adfDefinition ); if( dfLineTypeScale != 0.0 ) { osLineType = oPair.first; break; } } } // If not, create an automatic name for it. if( osLineType == "" ) { dfLineTypeScale = 1.0; do { osLineType.Printf( "AutoLineType-%d", nNextAutoID++ ); } while( poDS->oHeaderDS.LookupLineType(osLineType).size() > 0 ); } // If it isn't already defined, add it now. if( poDS->oHeaderDS.LookupLineType( osLineType ).empty() && oNewLineTypes.count( osLineType ) == 0 ) { oNewLineTypes[osLineType] = adfDefinition; } WriteValue( 6, osLineType ); if( dfLineTypeScale != 0.0 && fabs( dfLineTypeScale - 1.0 ) > 1e-4 ) { WriteValue( 48, dfLineTypeScale ); } } } /* -------------------------------------------------------------------- */ /* Write the vertices */ /* -------------------------------------------------------------------- */ if( !bHasDifferentZ && poLS->getGeometryType() == wkbLineString25D ) { // if LWPOLYLINE with Z write it only once if( !WriteValue( 38, poLS->getZ(0) ) ) return OGRERR_FAILURE; } for( int iVert = 0; iVert < poLS->getNumPoints(); iVert++ ) { if( bHasDifferentZ ) { WriteValue( 0, "VERTEX" ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbVertex" ); WriteValue( 100, "AcDb3dPolylineVertex" ); WriteCore( poFeature ); } WriteValue( 10, poLS->getX(iVert) ); if( !WriteValue( 20, poLS->getY(iVert) ) ) return OGRERR_FAILURE; if( bHasDifferentZ ) { if( !WriteValue( 30 , poLS->getZ(iVert) ) ) return OGRERR_FAILURE; WriteValue( 70, 32 ); } } if( bHasDifferentZ ) { WriteValue( 0, "SEQEND" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); } delete poTool; return OGRERR_NONE; #ifdef notdef /* -------------------------------------------------------------------- */ /* Alternate unmaintained implementation as a polyline entity. */ /* -------------------------------------------------------------------- */ WriteValue( 0, "POLYLINE" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbPolyline" ); if( EQUAL( poGeom->getGeometryName(), "LINEARRING" ) ) WriteValue( 70, 1 ); else WriteValue( 70, 0 ); WriteValue( 66, "1" ); for( int iVert = 0; iVert < poLS->getNumPoints(); iVert++ ) { WriteValue( 0, "VERTEX" ); WriteValue( 8, "0" ); WriteValue( 10, poLS->getX(iVert) ); if( !WriteValue( 20, poLS->getY(iVert) ) ) return OGRERR_FAILURE; if( poLS->getGeometryType() == wkbLineString25D ) { if( !WriteValue( 30, poLS->getZ(iVert) ) ) return OGRERR_FAILURE; } } WriteValue( 0, "SEQEND" ); WriteValue( 8, "0" ); return OGRERR_NONE; #endif }
OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature ) { WriteValue( 0, "MTEXT" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbMText" ); /* -------------------------------------------------------------------- */ /* Do we have styling information? */ /* -------------------------------------------------------------------- */ OGRStyleTool *poTool = nullptr; OGRStyleMgr oSM; if( poFeature->GetStyleString() != nullptr ) { oSM.InitFromFeature( poFeature ); if( oSM.GetPartCount() > 0 ) poTool = oSM.GetPart(0); } /* ==================================================================== */ /* Process the LABEL tool. */ /* ==================================================================== */ double dfDx = 0.0; double dfDy = 0.0; if( poTool && poTool->GetType() == OGRSTCLabel ) { OGRStyleLabel *poLabel = (OGRStyleLabel *) poTool; GBool bDefault; /* -------------------------------------------------------------------- */ /* Color */ /* -------------------------------------------------------------------- */ if( poLabel->ForeColor(bDefault) != nullptr && !bDefault ) WriteValue( 62, ColorStringToDXFColor( poLabel->ForeColor(bDefault) ) ); /* -------------------------------------------------------------------- */ /* Angle */ /* -------------------------------------------------------------------- */ const double dfAngle = poLabel->Angle(bDefault); if( !bDefault ) WriteValue( 50, dfAngle ); /* -------------------------------------------------------------------- */ /* Height - We need to fetch this in georeferenced units - I'm */ /* doubt the default translation mechanism will be much good. */ /* -------------------------------------------------------------------- */ poTool->SetUnit( OGRSTUGround ); const double dfHeight = poLabel->Size(bDefault); if( !bDefault ) WriteValue( 40, dfHeight ); /* -------------------------------------------------------------------- */ /* Anchor / Attachment Point */ /* -------------------------------------------------------------------- */ const int nAnchor = poLabel->Anchor(bDefault); if( !bDefault ) { const static int anAnchorMap[] = { -1, 7, 8, 9, 4, 5, 6, 1, 2, 3, 7, 8, 9 }; if( nAnchor > 0 && nAnchor < 13 ) WriteValue( 71, anAnchorMap[nAnchor] ); } /* -------------------------------------------------------------------- */ /* Offset */ /* -------------------------------------------------------------------- */ dfDx = poLabel->SpacingX(bDefault); dfDy = poLabel->SpacingY(bDefault); /* -------------------------------------------------------------------- */ /* Escape the text, and convert to ISO8859. */ /* -------------------------------------------------------------------- */ const char *pszText = poLabel->TextString( bDefault ); if( pszText != nullptr && !bDefault ) { CPLString osEscaped = TextEscape( pszText ); while( osEscaped.size() > 250 ) { WriteValue( 3, osEscaped.substr( 0, 250 ).c_str() ); osEscaped.erase( 0, 250 ); } WriteValue( 1, osEscaped ); } /* -------------------------------------------------------------------- */ /* Store the text style in the map. */ /* -------------------------------------------------------------------- */ std::map<CPLString, CPLString> oTextStyleDef = PrepareTextStyleDefinition( poLabel ); CPLString osStyleName; for( const auto& oPair: oNewTextStyles ) { if( oPair.second == oTextStyleDef ) { osStyleName = oPair.first; break; } } if( osStyleName == "" ) { do { osStyleName.Printf( "AutoTextStyle-%d", nNextAutoID++ ); } while( poDS->oHeaderDS.TextStyleExists( osStyleName ) ); oNewTextStyles[osStyleName] = oTextStyleDef; } WriteValue( 7, osStyleName ); } delete poTool; /* -------------------------------------------------------------------- */ /* Write the location. */ /* -------------------------------------------------------------------- */ OGRPoint *poPoint = poFeature->GetGeometryRef()->toPoint(); WriteValue( 10, poPoint->getX() + dfDx ); if( !WriteValue( 20, poPoint->getY() + dfDy ) ) return OGRERR_FAILURE; if( poPoint->getGeometryType() == wkbPoint25D ) { if( !WriteValue( 30, poPoint->getZ() ) ) return OGRERR_FAILURE; } return OGRERR_NONE; }
OGRErr OGRDXFWriterLayer::WriteINSERT( OGRFeature *poFeature ) { WriteValue( 0, "INSERT" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbBlockReference" ); WriteValue( 2, poFeature->GetFieldAsString("BlockName") ); // Write style symbol color OGRStyleTool *poTool = nullptr; OGRStyleMgr oSM; if( poFeature->GetStyleString() != nullptr ) { oSM.InitFromFeature( poFeature ); if( oSM.GetPartCount() > 0 ) poTool = oSM.GetPart(0); } if( poTool && poTool->GetType() == OGRSTCSymbol ) { OGRStyleSymbol *poSymbol = (OGRStyleSymbol *) poTool; GBool bDefault; if( poSymbol->Color(bDefault) != nullptr && !bDefault ) WriteValue( 62, ColorStringToDXFColor( poSymbol->Color(bDefault) ) ); } delete poTool; /* -------------------------------------------------------------------- */ /* Write location in OCS. */ /* -------------------------------------------------------------------- */ int nCoordCount = 0; const double *padfCoords = poFeature->GetFieldAsDoubleList( "BlockOCSCoords", &nCoordCount ); if( nCoordCount == 3 ) { WriteValue( 10, padfCoords[0] ); WriteValue( 20, padfCoords[1] ); if( !WriteValue( 30, padfCoords[2] ) ) return OGRERR_FAILURE; } else { // We don't have an OCS; we will just assume that the location of // the geometry (in WCS) is the correct insertion point. OGRPoint *poPoint = poFeature->GetGeometryRef()->toPoint(); WriteValue( 10, poPoint->getX() ); if( !WriteValue( 20, poPoint->getY() ) ) return OGRERR_FAILURE; if( poPoint->getGeometryType() == wkbPoint25D ) { if( !WriteValue( 30, poPoint->getZ() ) ) return OGRERR_FAILURE; } } /* -------------------------------------------------------------------- */ /* Write scaling. */ /* -------------------------------------------------------------------- */ int nScaleCount = 0; const double *padfScale = poFeature->GetFieldAsDoubleList( "BlockScale", &nScaleCount ); if( nScaleCount == 3 ) { WriteValue( 41, padfScale[0] ); WriteValue( 42, padfScale[1] ); WriteValue( 43, padfScale[2] ); } /* -------------------------------------------------------------------- */ /* Write rotation. */ /* -------------------------------------------------------------------- */ const double dfAngle = poFeature->GetFieldAsDouble( "BlockAngle" ); if( dfAngle != 0.0 ) { WriteValue( 50, dfAngle ); // degrees } /* -------------------------------------------------------------------- */ /* Write OCS normal vector. */ /* -------------------------------------------------------------------- */ int nOCSCount = 0; const double *padfOCS = poFeature->GetFieldAsDoubleList( "BlockOCSNormal", &nOCSCount ); if( nOCSCount == 3 ) { WriteValue( 210, padfOCS[0] ); WriteValue( 220, padfOCS[1] ); WriteValue( 230, padfOCS[2] ); } return OGRERR_NONE; }
OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature, OGRGeometry *poGeom ) { /* -------------------------------------------------------------------- */ /* For now we handle multipolygons by writing a series of */ /* entities. */ /* -------------------------------------------------------------------- */ if( poGeom == nullptr ) poGeom = poFeature->GetGeometryRef(); if ( poGeom->IsEmpty() ) { return OGRERR_NONE; } if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon ) { OGRErr eErr = OGRERR_NONE; for( auto&& poMember: poGeom->toMultiPolygon() ) { eErr = WriteHATCH( poFeature, poMember ); if( eErr != OGRERR_NONE ) break; } return eErr; } /* -------------------------------------------------------------------- */ /* Do we now have a geometry we can work with? */ /* -------------------------------------------------------------------- */ if( wkbFlatten(poGeom->getGeometryType()) != wkbPolygon && wkbFlatten(poGeom->getGeometryType()) != wkbTriangle ) { return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; } /* -------------------------------------------------------------------- */ /* Write as a hatch. */ /* -------------------------------------------------------------------- */ WriteValue( 0, "HATCH" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbHatch" ); // Figure out "average" elevation OGREnvelope3D oEnv; poGeom->getEnvelope( &oEnv ); WriteValue( 10, 0 ); // elevation point X = 0 WriteValue( 20, 0 ); // elevation point Y = 0 // elevation point Z = constant elevation WriteValue( 30, oEnv.MinZ + ( oEnv.MaxZ - oEnv.MinZ ) / 2 ); WriteValue(210, 0 ); // extrusion direction X WriteValue(220, 0 ); // extrusion direction Y WriteValue(230,1.0); // extrusion direction Z WriteValue( 2, "SOLID" ); // fill pattern WriteValue( 70, 1 ); // solid fill WriteValue( 71, 0 ); // associativity /* -------------------------------------------------------------------- */ /* Do we have styling information? */ /* -------------------------------------------------------------------- */ OGRStyleTool *poTool = nullptr; OGRStyleMgr oSM; if( poFeature->GetStyleString() != nullptr ) { oSM.InitFromFeature( poFeature ); if( oSM.GetPartCount() > 0 ) poTool = oSM.GetPart(0); } // Write style brush fore color if( poTool && poTool->GetType() == OGRSTCBrush ) { OGRStyleBrush *poBrush = (OGRStyleBrush *) poTool; GBool bDefault; if( poBrush->ForeColor(bDefault) != nullptr && !bDefault ) WriteValue( 62, ColorStringToDXFColor( poBrush->ForeColor(bDefault) ) ); } delete poTool; /* -------------------------------------------------------------------- */ /* Handle a PEN tool to control drawing color and width. */ /* Perhaps one day also dottedness, etc. */ /* -------------------------------------------------------------------- */ #ifdef notdef if( poTool && poTool->GetType() == OGRSTCPen ) { OGRStylePen *poPen = (OGRStylePen *) poTool; GBool bDefault; if( poPen->Color(bDefault) != NULL && !bDefault ) WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) ); double dfWidthInMM = poPen->Width(bDefault); if( !bDefault ) WriteValue( 370, (int) floor(dfWidthInMM * 100 + 0.5) ); } /* -------------------------------------------------------------------- */ /* Do we have a Linetype for the feature? */ /* -------------------------------------------------------------------- */ CPLString osLineType = poFeature->GetFieldAsString( "Linetype" ); if( !osLineType.empty() && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL || oNewLineTypes.count(osLineType) > 0 ) ) { // Already define -> just reference it. WriteValue( 6, osLineType ); } else if( poTool != NULL && poTool->GetType() == OGRSTCPen ) { CPLString osDefinition = PrepareLineTypeDefinition( poFeature, poTool ); if( osDefinition != "" && osLineType == "" ) { // Is this definition already created and named? std::map<CPLString,CPLString>::iterator it; for( it = oNewLineTypes.begin(); it != oNewLineTypes.end(); it++ ) { if( (*it).second == osDefinition ) { osLineType = (*it).first; break; } } // create an automatic name for it. if( osLineType == "" ) { do { osLineType.Printf( "AutoLineType-%d", nNextAutoID++ ); } while( poDS->oHeaderDS.LookupLineType(osLineType) != NULL ); } } // If it isn't already defined, add it now. if( osDefinition != "" && oNewLineTypes.count(osLineType) == 0 ) { oNewLineTypes[osLineType] = osDefinition; WriteValue( 6, osLineType ); } } delete poTool; #endif /* -------------------------------------------------------------------- */ /* Process the loops (rings). */ /* -------------------------------------------------------------------- */ OGRPolygon *poPoly = poGeom->toPolygon(); WriteValue( 91, poPoly->getNumInteriorRings() + 1 ); for( auto&& poLR: *poPoly ) { WriteValue( 92, 2 ); // Polyline WriteValue( 72, 0 ); // has bulge WriteValue( 73, 1 ); // is closed WriteValue( 93, poLR->getNumPoints() ); for( int iVert = 0; iVert < poLR->getNumPoints(); iVert++ ) { WriteValue( 10, poLR->getX(iVert) ); WriteValue( 20, poLR->getY(iVert) ); } WriteValue( 97, 0 ); // 0 source boundary objects } WriteValue( 75, 0 ); // hatch style = Hatch "odd parity" area (Normal style) WriteValue( 76, 1 ); // hatch pattern type = predefined WriteValue( 98, 0 ); // 0 seed points return OGRERR_NONE; #ifdef notdef /* -------------------------------------------------------------------- */ /* Alternate unmaintained implementation as a polyline entity. */ /* -------------------------------------------------------------------- */ WriteValue( 0, "POLYLINE" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbPolyline" ); if( EQUAL( poGeom->getGeometryName(), "LINEARRING" ) ) WriteValue( 70, 1 ); else WriteValue( 70, 0 ); WriteValue( 66, "1" ); for( int iVert = 0; iVert < poLS->getNumPoints(); iVert++ ) { WriteValue( 0, "VERTEX" ); WriteValue( 8, "0" ); WriteValue( 10, poLS->getX(iVert) ); if( !WriteValue( 20, poLS->getY(iVert) ) ) return OGRERR_FAILURE; if( poLS->getGeometryType() == wkbLineString25D ) { if( !WriteValue( 30, poLS->getZ(iVert) ) ) return OGRERR_FAILURE; } } WriteValue( 0, "SEQEND" ); WriteValue( 8, "0" ); return OGRERR_NONE; #endif }
OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature, OGRGeometry *poGeom ) { /* -------------------------------------------------------------------- */ /* For now we handle multilinestrings by writing a series of */ /* entities. */ /* -------------------------------------------------------------------- */ if( poGeom == NULL ) poGeom = poFeature->GetGeometryRef(); if ( poGeom->IsEmpty() ) { return OGRERR_NONE; } if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon || wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString ) { OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom; int iGeom; OGRErr eErr = OGRERR_NONE; for( iGeom = 0; eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries(); iGeom++ ) { eErr = WritePOLYLINE( poFeature, poGC->getGeometryRef( iGeom ) ); } return eErr; } /* -------------------------------------------------------------------- */ /* Polygons are written with on entity per ring. */ /* -------------------------------------------------------------------- */ if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ) { OGRPolygon *poPoly = (OGRPolygon *) poGeom; int iGeom; OGRErr eErr; eErr = WritePOLYLINE( poFeature, poPoly->getExteriorRing() ); for( iGeom = 0; eErr == OGRERR_NONE && iGeom < poPoly->getNumInteriorRings(); iGeom++ ) { eErr = WritePOLYLINE( poFeature, poPoly->getInteriorRing(iGeom) ); } return eErr; } /* -------------------------------------------------------------------- */ /* Do we now have a geometry we can work with? */ /* -------------------------------------------------------------------- */ if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString ) return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; OGRLineString *poLS = (OGRLineString *) poGeom; /* -------------------------------------------------------------------- */ /* Write as a lightweight polygon, */ /* or as POLYLINE if the line contains different heights */ /* -------------------------------------------------------------------- */ int bHasDifferentZ = FALSE; if( poLS->getGeometryType() == wkbLineString25D ) { double z0 = poLS->getZ(0); for( int iVert = 0; iVert < poLS->getNumPoints(); iVert++ ) { if (z0 != poLS->getZ(iVert)) { bHasDifferentZ = TRUE; break; } } } WriteValue( 0, bHasDifferentZ ? "POLYLINE" : "LWPOLYLINE" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); if( bHasDifferentZ ) { WriteValue( 100, "AcDb3dPolyline" ); WriteValue( 10, 0.0 ); WriteValue( 20, 0.0 ); WriteValue( 30, 0.0 ); } else WriteValue( 100, "AcDbPolyline" ); if( EQUAL( poGeom->getGeometryName(), "LINEARRING" ) ) WriteValue( 70, 1 + (bHasDifferentZ ? 8 : 0) ); else WriteValue( 70, 0 + (bHasDifferentZ ? 8 : 0) ); if( !bHasDifferentZ ) WriteValue( 90, poLS->getNumPoints() ); else WriteValue( 66, "1" ); // Vertex Flag /* -------------------------------------------------------------------- */ /* Do we have styling information? */ /* -------------------------------------------------------------------- */ OGRStyleTool *poTool = NULL; OGRStyleMgr oSM; if( poFeature->GetStyleString() != NULL ) { oSM.InitFromFeature( poFeature ); if( oSM.GetPartCount() > 0 ) poTool = oSM.GetPart(0); } /* -------------------------------------------------------------------- */ /* Handle a PEN tool to control drawing color and width. */ /* Perhaps one day also dottedness, etc. */ /* -------------------------------------------------------------------- */ if( poTool && poTool->GetType() == OGRSTCPen ) { OGRStylePen *poPen = (OGRStylePen *) poTool; GBool bDefault; if( poPen->Color(bDefault) != NULL && !bDefault ) WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) ); // we want to fetch the width in ground units. poPen->SetUnit( OGRSTUGround, 1.0 ); double dfWidth = poPen->Width(bDefault); if( !bDefault ) WriteValue( 370, (int) floor(dfWidth * 100 + 0.5) ); } /* -------------------------------------------------------------------- */ /* Do we have a Linetype for the feature? */ /* -------------------------------------------------------------------- */ CPLString osLineType = poFeature->GetFieldAsString( "Linetype" ); if( osLineType.size() > 0 && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL || oNewLineTypes.count(osLineType) > 0 ) ) { // Already define -> just reference it. WriteValue( 6, osLineType ); } else if( poTool != NULL && poTool->GetType() == OGRSTCPen ) { CPLString osDefinition = PrepareLineTypeDefinition( poFeature, poTool ); if( osDefinition != "" && osLineType == "" ) { // Is this definition already created and named? std::map<CPLString,CPLString>::iterator it; for( it = oNewLineTypes.begin(); it != oNewLineTypes.end(); it++ ) { if( (*it).second == osDefinition ) { osLineType = (*it).first; break; } } // create an automatic name for it. if( osLineType == "" ) { do { osLineType.Printf( "AutoLineType-%d", nNextAutoID++ ); } while( poDS->oHeaderDS.LookupLineType(osLineType) != NULL ); } } // If it isn't already defined, add it now. if( osDefinition != "" && oNewLineTypes.count(osLineType) == 0 ) { oNewLineTypes[osLineType] = osDefinition; WriteValue( 6, osLineType ); } } /* -------------------------------------------------------------------- */ /* Write the vertices */ /* -------------------------------------------------------------------- */ if( !bHasDifferentZ && poLS->getGeometryType() == wkbLineString25D ) { // if LWPOLYLINE with Z write it only once if( !WriteValue( 38, poLS->getZ(0) ) ) return OGRERR_FAILURE; } int iVert; for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ ) { if( bHasDifferentZ ) { WriteValue( 0, "VERTEX" ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbVertex" ); WriteValue( 100, "AcDb3dPolylineVertex" ); WriteCore( poFeature ); } WriteValue( 10, poLS->getX(iVert) ); if( !WriteValue( 20, poLS->getY(iVert) ) ) return OGRERR_FAILURE; if( bHasDifferentZ ) { if( !WriteValue( 30 , poLS->getZ(iVert) ) ) return OGRERR_FAILURE; WriteValue( 70, 32 ); } } if( bHasDifferentZ ) { WriteValue( 0, "SEQEND" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); } delete poTool; return OGRERR_NONE; #ifdef notdef /* -------------------------------------------------------------------- */ /* Alternate unmaintained implementation as a polyline entity. */ /* -------------------------------------------------------------------- */ WriteValue( 0, "POLYLINE" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbPolyline" ); if( EQUAL( poGeom->getGeometryName(), "LINEARRING" ) ) WriteValue( 70, 1 ); else WriteValue( 70, 0 ); WriteValue( 66, "1" ); int iVert; for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ ) { WriteValue( 0, "VERTEX" ); WriteValue( 8, "0" ); WriteValue( 10, poLS->getX(iVert) ); if( !WriteValue( 20, poLS->getY(iVert) ) ) return OGRERR_FAILURE; if( poLS->getGeometryType() == wkbLineString25D ) { if( !WriteValue( 30, poLS->getZ(iVert) ) ) return OGRERR_FAILURE; } } WriteValue( 0, "SEQEND" ); WriteValue( 8, "0" ); return OGRERR_NONE; #endif }
OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature ) { WriteValue( 0, "MTEXT" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbMText" ); /* -------------------------------------------------------------------- */ /* Do we have styling information? */ /* -------------------------------------------------------------------- */ OGRStyleTool *poTool = NULL; OGRStyleMgr oSM; if( poFeature->GetStyleString() != NULL ) { oSM.InitFromFeature( poFeature ); if( oSM.GetPartCount() > 0 ) poTool = oSM.GetPart(0); } /* ==================================================================== */ /* Process the LABEL tool. */ /* ==================================================================== */ if( poTool && poTool->GetType() == OGRSTCLabel ) { OGRStyleLabel *poLabel = (OGRStyleLabel *) poTool; GBool bDefault; /* -------------------------------------------------------------------- */ /* Color */ /* -------------------------------------------------------------------- */ if( poLabel->ForeColor(bDefault) != NULL && !bDefault ) WriteValue( 62, ColorStringToDXFColor( poLabel->ForeColor(bDefault) ) ); /* -------------------------------------------------------------------- */ /* Angle */ /* -------------------------------------------------------------------- */ double dfAngle = poLabel->Angle(bDefault); // The DXF2000 reference says this is in radians, but in files // I see it seems to be in degrees. Perhaps this is version dependent? if( !bDefault ) WriteValue( 50, dfAngle ); /* -------------------------------------------------------------------- */ /* Height - We need to fetch this in georeferenced units - I'm */ /* doubt the default translation mechanism will be much good. */ /* -------------------------------------------------------------------- */ poTool->SetUnit( OGRSTUGround ); double dfHeight = poLabel->Size(bDefault); if( !bDefault ) WriteValue( 40, dfHeight ); /* -------------------------------------------------------------------- */ /* Anchor / Attachment Point */ /* -------------------------------------------------------------------- */ int nAnchor = poLabel->Anchor(bDefault); if( !bDefault ) { const static int anAnchorMap[] = { -1, 7, 8, 9, 4, 5, 6, 1, 2, 3, 7, 8, 9 }; if( nAnchor > 0 && nAnchor < 13 ) WriteValue( 71, anAnchorMap[nAnchor] ); } /* -------------------------------------------------------------------- */ /* Escape the text, and convert to ISO8859. */ /* -------------------------------------------------------------------- */ const char *pszText = poLabel->TextString( bDefault ); if( pszText != NULL && !bDefault ) { CPLString osEscaped = TextEscape( pszText ); WriteValue( 1, osEscaped ); } } delete poTool; /* -------------------------------------------------------------------- */ /* Write the location. */ /* -------------------------------------------------------------------- */ OGRPoint *poPoint = (OGRPoint *) poFeature->GetGeometryRef(); WriteValue( 10, poPoint->getX() ); if( !WriteValue( 20, poPoint->getY() ) ) return OGRERR_FAILURE; if( poPoint->getGeometryType() == wkbPoint25D ) { if( !WriteValue( 30, poPoint->getZ() ) ) return OGRERR_FAILURE; } return OGRERR_NONE; }
OGRErr OGRDXFWriterLayer::WriteINSERT( OGRFeature *poFeature ) { WriteValue( 0, "INSERT" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbBlockReference" ); WriteValue( 2, poFeature->GetFieldAsString("BlockName") ); // Write style symbol color OGRStyleTool *poTool = NULL; OGRStyleMgr oSM; if( poFeature->GetStyleString() != NULL ) { oSM.InitFromFeature( poFeature ); if( oSM.GetPartCount() > 0 ) poTool = oSM.GetPart(0); } if( poTool && poTool->GetType() == OGRSTCSymbol ) { OGRStyleSymbol *poSymbol = (OGRStyleSymbol *) poTool; GBool bDefault; if( poSymbol->Color(bDefault) != NULL && !bDefault ) WriteValue( 62, ColorStringToDXFColor( poSymbol->Color(bDefault) ) ); } delete poTool; /* -------------------------------------------------------------------- */ /* Write location. */ /* -------------------------------------------------------------------- */ OGRPoint *poPoint = (OGRPoint *) poFeature->GetGeometryRef(); WriteValue( 10, poPoint->getX() ); if( !WriteValue( 20, poPoint->getY() ) ) return OGRERR_FAILURE; if( poPoint->getGeometryType() == wkbPoint25D ) { if( !WriteValue( 30, poPoint->getZ() ) ) return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Write scaling. */ /* -------------------------------------------------------------------- */ int nScaleCount; const double *padfScale = poFeature->GetFieldAsDoubleList( "BlockScale", &nScaleCount ); if( nScaleCount == 3 ) { WriteValue( 41, padfScale[0] ); WriteValue( 42, padfScale[1] ); WriteValue( 43, padfScale[2] ); } /* -------------------------------------------------------------------- */ /* Write rotation. */ /* -------------------------------------------------------------------- */ double dfAngle = poFeature->GetFieldAsDouble( "BlockAngle" ); if( dfAngle != 0.0 ) { WriteValue( 50, dfAngle ); // degrees } return OGRERR_NONE; }
OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature, OGRGeometry *poGeom ) { /* -------------------------------------------------------------------- */ /* For now we handle multipolygons by writing a series of */ /* entities. */ /* -------------------------------------------------------------------- */ if( poGeom == NULL ) poGeom = poFeature->GetGeometryRef(); if ( poGeom->IsEmpty() ) { return OGRERR_NONE; } if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon ) { OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom; int iGeom; OGRErr eErr = OGRERR_NONE; for( iGeom = 0; eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries(); iGeom++ ) { eErr = WriteHATCH( poFeature, poGC->getGeometryRef( iGeom ) ); } return eErr; } /* -------------------------------------------------------------------- */ /* Do we now have a geometry we can work with? */ /* -------------------------------------------------------------------- */ if( wkbFlatten(poGeom->getGeometryType()) != wkbPolygon ) return OGRERR_UNSUPPORTED_GEOMETRY_TYPE; /* -------------------------------------------------------------------- */ /* Write as a hatch. */ /* -------------------------------------------------------------------- */ WriteValue( 0, "HATCH" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbHatch" ); WriteValue( 2, "SOLID" ); // fill pattern WriteValue( 70, 1 ); // solid fill WriteValue( 71, 0 ); // associativity /* -------------------------------------------------------------------- */ /* Do we have styling information? */ /* -------------------------------------------------------------------- */ OGRStyleTool *poTool = NULL; OGRStyleMgr oSM; if( poFeature->GetStyleString() != NULL ) { oSM.InitFromFeature( poFeature ); if( oSM.GetPartCount() > 0 ) poTool = oSM.GetPart(0); } /* -------------------------------------------------------------------- */ /* Handle a PEN tool to control drawing color and width. */ /* Perhaps one day also dottedness, etc. */ /* -------------------------------------------------------------------- */ #ifdef notdef if( poTool && poTool->GetType() == OGRSTCPen ) { OGRStylePen *poPen = (OGRStylePen *) poTool; GBool bDefault; if( poPen->Color(bDefault) != NULL && !bDefault ) WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) ); double dfWidthInMM = poPen->Width(bDefault); if( !bDefault ) WriteValue( 370, (int) floor(dfWidthInMM * 100 + 0.5) ); } /* -------------------------------------------------------------------- */ /* Do we have a Linetype for the feature? */ /* -------------------------------------------------------------------- */ CPLString osLineType = poFeature->GetFieldAsString( "Linetype" ); if( osLineType.size() > 0 && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL || oNewLineTypes.count(osLineType) > 0 ) ) { // Already define -> just reference it. WriteValue( 6, osLineType ); } else if( poTool != NULL && poTool->GetType() == OGRSTCPen ) { CPLString osDefinition = PrepareLineTypeDefinition( poFeature, poTool ); if( osDefinition != "" && osLineType == "" ) { // Is this definition already created and named? std::map<CPLString,CPLString>::iterator it; for( it = oNewLineTypes.begin(); it != oNewLineTypes.end(); it++ ) { if( (*it).second == osDefinition ) { osLineType = (*it).first; break; } } // create an automatic name for it. if( osLineType == "" ) { do { osLineType.Printf( "AutoLineType-%d", nNextAutoID++ ); } while( poDS->oHeaderDS.LookupLineType(osLineType) != NULL ); } } // If it isn't already defined, add it now. if( osDefinition != "" && oNewLineTypes.count(osLineType) == 0 ) { oNewLineTypes[osLineType] = osDefinition; WriteValue( 6, osLineType ); } } delete poTool; #endif /* -------------------------------------------------------------------- */ /* Process the loops (rings). */ /* -------------------------------------------------------------------- */ OGRPolygon *poPoly = (OGRPolygon *) poGeom; WriteValue( 91, poPoly->getNumInteriorRings() + 1 ); for( int iRing = -1; iRing < poPoly->getNumInteriorRings(); iRing++ ) { OGRLinearRing *poLR; if( iRing == -1 ) poLR = poPoly->getExteriorRing(); else poLR = poPoly->getInteriorRing( iRing ); WriteValue( 92, 2 ); // Polyline WriteValue( 72, 0 ); // has bulge WriteValue( 73, 1 ); // is closed WriteValue( 93, poLR->getNumPoints() ); for( int iVert = 0; iVert < poLR->getNumPoints(); iVert++ ) { WriteValue( 10, poLR->getX(iVert) ); WriteValue( 20, poLR->getY(iVert) ); } } return OGRERR_NONE; #ifdef notdef /* -------------------------------------------------------------------- */ /* Alternate unmaintained implementation as a polyline entity. */ /* -------------------------------------------------------------------- */ WriteValue( 0, "POLYLINE" ); WriteCore( poFeature ); WriteValue( 100, "AcDbEntity" ); WriteValue( 100, "AcDbPolyline" ); if( EQUAL( poGeom->getGeometryName(), "LINEARRING" ) ) WriteValue( 70, 1 ); else WriteValue( 70, 0 ); WriteValue( 66, "1" ); int iVert; for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ ) { WriteValue( 0, "VERTEX" ); WriteValue( 8, "0" ); WriteValue( 10, poLS->getX(iVert) ); if( !WriteValue( 20, poLS->getY(iVert) ) ) return OGRERR_FAILURE; if( poLS->getGeometryType() == wkbLineString25D ) { if( !WriteValue( 30, poLS->getZ(iVert) ) ) return OGRERR_FAILURE; } } WriteValue( 0, "SEQEND" ); WriteValue( 8, "0" ); return OGRERR_NONE; #endif }