Skip to content

Commit

Permalink
DXF: defer inlining of blocks until actually required (patch by Alan …
Browse files Browse the repository at this point in the history
…Thomas, fixes #7106, #251)

git-svn-id: https://svn.osgeo.org/gdal/trunk@40548 f0d54148-0727-0410-94bb-9a71ac55c965
  • Loading branch information
rouault committed Oct 24, 2017
1 parent 9a7a7d1 commit 4215dbb
Show file tree
Hide file tree
Showing 17 changed files with 1,543 additions and 427 deletions.
722 changes: 722 additions & 0 deletions autotest/ogr/data/block-insert-order.dxf

Large diffs are not rendered by default.

109 changes: 96 additions & 13 deletions autotest/ogr/ogr_dxf.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,16 @@ def ogr_dxf_16():
gdaltest.post_reason( 'did not get expected layer name.' )
return 'fail'

# STAR geometry
feat = dxf_layer.GetNextFeature()

if feat.GetField('Block') != 'STAR':
gdaltest.post_reason( 'Did not get expected block name.' )
return 'fail'

if ogrtest.check_feature_geometry( feat, 'MULTILINESTRING ((-0.028147497671066 1.041457413829428 0,0.619244948763444 -1.069604911500494 0),(0.619244948763444 -1.069604911500494 0,-0.957014920816232 0.478507460408116 0),(-0.957014920816232 0.478507460408116 0,1.041457413829428 0.365917469723853 0),(1.041457413829428 0.365917469723853 0,-0.478507460408116 -1.041457413829428 0),(-0.478507460408116 -1.041457413829428 0,-0.056294995342131 1.013309916158363 0))' ):
return 'fail'

# First MTEXT
feat = dxf_layer.GetNextFeature()
if feat.GetField( 'Text' ) != gdaltest.sample_text:
Expand Down Expand Up @@ -751,16 +761,6 @@ def ogr_dxf_16():
if ogrtest.check_feature_geometry( feat, 'POINT (0.879677852348995 -0.263903355704699 0)' ):
return 'fail'

# STAR geometry
feat = dxf_layer.GetNextFeature()

if feat.GetField('BlockName') != 'STAR':
gdaltest.post_reason( 'Did not get expected block name.' )
return 'fail'

if ogrtest.check_feature_geometry( feat, 'MULTILINESTRING ((-0.028147497671066 1.041457413829428 0,0.619244948763444 -1.069604911500494 0),(0.619244948763444 -1.069604911500494 0,-0.957014920816232 0.478507460408116 0),(-0.957014920816232 0.478507460408116 0,1.041457413829428 0.365917469723853 0),(1.041457413829428 0.365917469723853 0,-0.478507460408116 -1.041457413829428 0),(-0.478507460408116 -1.041457413829428 0,-0.056294995342131 1.013309916158363 0))' ):
return 'fail'

feat = None

# cleanup
Expand All @@ -783,21 +783,21 @@ def ogr_dxf_17():
dst_feat = ogr.Feature( feature_def = blyr.GetLayerDefn() )
dst_feat.SetGeometryDirectly( ogr.CreateGeometryFromWkt(
'GEOMETRYCOLLECTION( LINESTRING(0 0,1 1),LINESTRING(1 0,0 1))' ) )
dst_feat.SetField( 'BlockName', 'XMark' )
dst_feat.SetField( 'Block', 'XMark' )
blyr.CreateFeature( dst_feat )

# Block with 2 polygons
dst_feat = ogr.Feature( feature_def = blyr.GetLayerDefn() )
dst_feat.SetGeometryDirectly( ogr.CreateGeometryFromWkt(
'GEOMETRYCOLLECTION( POLYGON((10 10,10 20,20 20,20 10,10 10)),POLYGON((10 -10,10 -20,20 -20,20 -10,10 -10)))' ) )
dst_feat.SetField( 'BlockName', 'Block2' )
dst_feat.SetField( 'Block', 'Block2' )
blyr.CreateFeature( dst_feat )

# Block with point and line
dst_feat = ogr.Feature( feature_def = blyr.GetLayerDefn() )
dst_feat.SetGeometryDirectly( ogr.CreateGeometryFromWkt(
'GEOMETRYCOLLECTION( POINT(1 2),LINESTRING(0 0,1 1))' ) )
dst_feat.SetField( 'BlockName', 'Block3' )
dst_feat.SetField( 'Block', 'Block3' )
blyr.CreateFeature( dst_feat )

# Write a block reference feature.
Expand Down Expand Up @@ -2716,6 +2716,88 @@ def ogr_dxf_41():

return 'success'

###############################################################################
# Test insertion of blocks within blocks (#7106)

def ogr_dxf_42():

# Inlining, merging
ds = ogr.Open('data/block-insert-order.dxf')
lyr = ds.GetLayer(0)
if lyr.GetFeatureCount() != 2:
gdaltest.post_reason( 'Defaults: Expected 2 features, found %d' % lyr.GetFeatureCount() )
return 'fail'

# No inlining, merging
gdal.SetConfigOption('DXF_INLINE_BLOCKS', 'FALSE')
ds = ogr.Open('data/block-insert-order.dxf')
gdal.SetConfigOption('DXF_INLINE_BLOCKS', None)

lyr = ds.GetLayerByName('entities')
if lyr.GetFeatureCount() != 2:
gdaltest.post_reason( 'No inlining: Expected 2 features on entities, found %d' % lyr.GetFeatureCount() )
return 'fail'

f = lyr.GetNextFeature()
if ogrtest.check_feature_geometry(f, 'POINT Z (0 0 0)') != 0:
gdaltest.post_reason( 'Wrong geometry for first insertion point' )
f.DumpReadable()
return 'fail'

f = lyr.GetNextFeature()
if ogrtest.check_feature_geometry(f, 'POINT Z (-1 -2 -3)') != 0:
gdaltest.post_reason( 'Wrong geometry for second insertion point' )
f.DumpReadable()
return 'fail'

lyr = ds.GetLayerByName('blocks')
if lyr.GetFeatureCount() != 6:
gdaltest.post_reason( 'No inlining: Expected 6 feature on blocks, found %d' % lyr.GetFeatureCount() )
return 'fail'

f = lyr.GetFeature(3)
if ogrtest.check_feature_geometry(f, 'POINT Z (5 5 0)') != 0:
gdaltest.post_reason( 'Wrong geometry for second insertion of BLOCK4 on BLOCK3' )
f.DumpReadable()
return 'fail'

f = lyr.GetFeature(4)
if ogrtest.check_feature_geometry(f, 'POINT Z (-5.48795472456028 1.69774937525433 4.12310562561766)') != 0:
gdaltest.post_reason( 'Wrong geometry for third insertion of BLOCK4 on BLOCK3' )
f.DumpReadable()
return 'fail'

if f.GetField('BlockName') != 'BLOCK4':
gdaltest.post_reason( 'Wrong BlockName' )
return 'fail'
if f.GetField('BlockScale') != [0.4,1.0,1.5]:
gdaltest.post_reason( 'Wrong BlockScale' )
return 'fail'
if f.GetField('BlockAngle') != 40:
gdaltest.post_reason( 'Wrong BlockAngle' )
return 'fail'
if f.GetField('BlockOCSNormal') != [0.6,0.565685424949238,0.565685424949238]:
gdaltest.post_reason( 'Wrong BlockOCSNormal' )
return 'fail'
if f.GetField('BlockOCSCoords') != [5,5,0]:
gdaltest.post_reason( 'Wrong BlockOCSCoords' )
return 'fail'
if f.GetField('Block') != 'BLOCK3':
gdaltest.post_reason( 'Wrong Block' )
return 'fail'

# Inlining, no merging
gdal.SetConfigOption('DXF_MERGE_BLOCK_GEOMETRIES', 'FALSE')
ds = ogr.Open('data/block-insert-order.dxf')
gdal.SetConfigOption('DXF_MERGE_BLOCK_GEOMETRIES', None)

lyr = ds.GetLayer(0)
if lyr.GetFeatureCount() != 4:
gdaltest.post_reason( 'Merging: Expected 4 features, found %d' % lyr.GetFeatureCount() )
return 'fail'

return 'success'

###############################################################################
# cleanup

Expand Down Expand Up @@ -2770,6 +2852,7 @@ def ogr_dxf_cleanup():
ogr_dxf_39,
ogr_dxf_40,
ogr_dxf_41,
ogr_dxf_42,
ogr_dxf_cleanup ]

if __name__ == '__main__':
Expand Down
2 changes: 2 additions & 0 deletions gdal/ogr/ogr_feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ class CPL_DLL OGRFeature
char *m_pszTmpFieldValue;
//! @endcond

bool CopySelfTo( OGRFeature *poNew );

public:
explicit OGRFeature( OGRFeatureDefn * );
virtual ~OGRFeature();
Expand Down
92 changes: 56 additions & 36 deletions gdal/ogr/ogrfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -880,12 +880,61 @@ OGRFeature *OGRFeature::Clone()
if( poNew == NULL )
return NULL;

if( !CopySelfTo( poNew ) )
{
delete poNew;
return NULL;
}

return poNew;
}

/************************************************************************/
/* OGR_F_Clone() */
/************************************************************************/

/**
* \brief Duplicate feature.
*
* The newly created feature is owned by the caller, and will have it's own
* reference to the OGRFeatureDefn.
*
* This function is the same as the C++ method OGRFeature::Clone().
*
* @param hFeat handle to the feature to clone.
* @return an handle to the new feature, exactly matching this feature.
*/

OGRFeatureH OGR_F_Clone( OGRFeatureH hFeat )

{
VALIDATE_POINTER1( hFeat, "OGR_F_Clone", NULL );

return reinterpret_cast<OGRFeatureH>(
reinterpret_cast<OGRFeature *>(hFeat)->Clone());
}

/************************************************************************/
/* CopySelfTo() */
/************************************************************************/

/**
* \brief Copies the innards of this OGRFeature into the supplied object.
*
* This is mainly intended to allow derived classes to implement their own
* Clone functions.
*
* @param poNew The object into which to copy the data of this object.
* @return True if successful, false if the copy failed.
*/

bool OGRFeature::CopySelfTo( OGRFeature* poNew )
{
for( int i = 0; i < poDefn->GetFieldCount(); i++ )
{
if( !poNew->SetFieldInternal( i, pauFields + i ) )
{
delete poNew;
return NULL;
return false;
}
}
if( poNew->papoGeometries )
Expand All @@ -897,8 +946,7 @@ OGRFeature *OGRFeature::Clone()
poNew->papoGeometries[i] = papoGeometries[i]->clone();
if( poNew->papoGeometries[i] == NULL )
{
delete poNew;
return NULL;
return false;
}
}
}
Expand All @@ -909,8 +957,7 @@ OGRFeature *OGRFeature::Clone()
poNew->m_pszStyleString = VSI_STRDUP_VERBOSE(m_pszStyleString);
if( poNew->m_pszStyleString == NULL )
{
delete poNew;
return NULL;
return false;
}
}

Expand All @@ -921,8 +968,7 @@ OGRFeature *OGRFeature::Clone()
poNew->m_pszNativeData = VSI_STRDUP_VERBOSE(m_pszNativeData);
if( poNew->m_pszNativeData == NULL )
{
delete poNew;
return NULL;
return false;
}
}

Expand All @@ -931,37 +977,11 @@ OGRFeature *OGRFeature::Clone()
poNew->m_pszNativeMediaType = VSI_STRDUP_VERBOSE(m_pszNativeMediaType);
if( poNew->m_pszNativeMediaType == NULL )
{
delete poNew;
return NULL;
return false;
}
}

return poNew;
}

/************************************************************************/
/* OGR_F_Clone() */
/************************************************************************/

/**
* \brief Duplicate feature.
*
* The newly created feature is owned by the caller, and will have it's own
* reference to the OGRFeatureDefn.
*
* This function is the same as the C++ method OGRFeature::Clone().
*
* @param hFeat handle to the feature to clone.
* @return an handle to the new feature, exactly matching this feature.
*/

OGRFeatureH OGR_F_Clone( OGRFeatureH hFeat )

{
VALIDATE_POINTER1( hFeat, "OGR_F_Clone", NULL );

return reinterpret_cast<OGRFeatureH>(
reinterpret_cast<OGRFeature *>(hFeat)->Clone());
return true;
}

/************************************************************************/
Expand Down
2 changes: 1 addition & 1 deletion gdal/ogr/ogrsf_frmts/dxf/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ OBJ = ogrdxfdriver.o ogrdxfdatasource.o ogrdxflayer.o \
ogrdxfwriterds.o ogrdxfwriterlayer.o intronurbs.o \
ogrdxf_polyline_smooth.o ogrdxfblockslayer.o \
ogrdxfblockswriterlayer.o ogrdxf_hatch.o \
ogr_autocad_services.o
ogr_autocad_services.o ogrdxf_feature.o

CPPFLAGS := -I.. -I../.. $(CPPFLAGS)

Expand Down
Loading

0 comments on commit 4215dbb

Please sign in to comment.