Skip to content

Commit

Permalink
MITAB: take into account scale/bounds to properly round coordinates (m…
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Aug 4, 2014
1 parent d112af7 commit 1580c26
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 63 deletions.
Binary file added autotest/ogr/data/utm31.DAT
Binary file not shown.
Binary file added autotest/ogr/data/utm31.ID
Binary file not shown.
Binary file added autotest/ogr/data/utm31.MAP
Binary file not shown.
13 changes: 13 additions & 0 deletions autotest/ogr/data/utm31.TAB
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
!table
!version 300
!charset WindowsLatin1

Definition Table
Type NATIVE Charset "WindowsLatin1"
Fields 1
id Integer ;
begin_metadata
"\IsReadOnly" = "FALSE"
"\MapInfo" = ""
"\MapInfo\TableID" = "f0bbc21d-6931-48be-b3f1-91f14480e738"
end_metadata
22 changes: 22 additions & 0 deletions autotest/ogr/ogr_mitab.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ def ogr_mitab_18():
wkt = sr_got.ExportToWkt()
if wkt.find('2154') < 0:
gdaltest.post_reason('failure')
print(filename)
print(sr_got)
return 'fail'
proj4 = sr_got.ExportToProj4()
Expand All @@ -607,6 +608,26 @@ def ogr_mitab_18():
ogr.GetDriverByName('MapInfo File').DeleteDataSource('/vsimem/ogr_mitab_18.tab')

return 'success'

###############################################################################
# Check that we correctly round coordinate to the appropriate precision
# (https://github.com/mapgears/mitab/issues/2)

def ogr_mitab_19():

if gdaltest.mapinfo_drv is None:
return 'skip'

ds = ogr.Open('data/utm31.TAB')
lyr = ds.GetLayer(0)
feat = lyr.GetNextFeature()
# Strict text comparison to check precision
if feat.GetGeometryRef().ExportToWkt() != 'POINT (485248.12 2261.45)':
feat.DumpReadable()
return 'fail'

return 'success'

###############################################################################
#

Expand Down Expand Up @@ -640,6 +661,7 @@ def ogr_mitab_cleanup():
ogr_mitab_16,
ogr_mitab_17,
ogr_mitab_18,
ogr_mitab_19,
ogr_mitab_cleanup
]

Expand Down
2 changes: 2 additions & 0 deletions gdal/ogr/ogrsf_frmts/mitab/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ default: $(O_OBJ:.o=.$(OBJ_EXT))
clean:
rm -f *.o $(O_OBJ)

$(O_OBJ): mitab.h mitab_priv.h

update:
copymatch.sh ~/pkg/mitab *.TXT
copymatch.sh ~/pkg/mitab/mitab *.cpp *.h
115 changes: 53 additions & 62 deletions gdal/ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@

#include "mitab.h"

#ifdef WIN32
inline double round(double r) {
return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}
#endif

/*---------------------------------------------------------------------
* Set various constants used in generating the header block.
*--------------------------------------------------------------------*/
Expand Down Expand Up @@ -178,6 +184,27 @@ static GByte gabyObjLenArray[ HDR_OBJ_LEN_ARRAY_SIZE ] = {
**********************************************************************/
TABMAPHeaderBlock::TABMAPHeaderBlock(TABAccess eAccessMode /*= TABRead*/):
TABRawBinBlock(eAccessMode, TRUE)
{
InitMembersWithDefaultValues();

/* We don't want to reset it once it is set */
m_bIntBoundsOverflow = FALSE;
}

/**********************************************************************
* TABMAPHeaderBlock::~TABMAPHeaderBlock()
*
* Destructor.
**********************************************************************/
TABMAPHeaderBlock::~TABMAPHeaderBlock()
{

}

/**********************************************************************
* TABMAPHeaderBlock::InitMembersWithDefaultValues()
**********************************************************************/
void TABMAPHeaderBlock::InitMembersWithDefaultValues()
{
int i;

Expand Down Expand Up @@ -207,7 +234,7 @@ TABMAPHeaderBlock::TABMAPHeaderBlock(TABAccess eAccessMode /*= TABRead*/):
m_nDistUnitsCode = 7; // Meters
m_nMaxSpIndexDepth = 0;
m_nCoordPrecision = 3; // ??? 3 Digits of precision
m_nCoordOriginQuadrant = HDR_DEF_ORG_QUADRANT; // ???
m_nCoordOriginQuadrant = HDR_DEF_ORG_QUADRANT; // ??? N-E quadrant
m_nReflectXAxisCoord = HDR_DEF_REFLECTXAXIS;
m_nMaxObjLenArrayId = HDR_OBJ_LEN_ARRAY_SIZE-1; // See gabyObjLenArray[]
m_numPenDefs = 0;
Expand All @@ -219,10 +246,13 @@ TABMAPHeaderBlock::TABMAPHeaderBlock(TABAccess eAccessMode /*= TABRead*/):
m_sProj.nProjId = 0;
m_sProj.nEllipsoidId = 0;
m_sProj.nUnitsId = 7;
m_sProj.nDatumId = 0;
m_XScale = 1000.0; // Default coord range (before SetCoordSysBounds())
m_YScale = 1000.0; // will be [-1000000.000 .. 1000000.000]
m_XDispl = 0.0;
m_YDispl = 0.0;
m_XPrecision = 0.0; // not specified
m_YPrecision = 0.0; // not specified

for(i=0; i<6; i++)
m_sProj.adProjParams[i] = 0.0;
Expand All @@ -243,16 +273,6 @@ TABMAPHeaderBlock::TABMAPHeaderBlock(TABAccess eAccessMode /*= TABRead*/):
m_sProj.dAffineParamF = 0.0;
}

/**********************************************************************
* TABMAPHeaderBlock::~TABMAPHeaderBlock()
*
* Destructor.
**********************************************************************/
TABMAPHeaderBlock::~TABMAPHeaderBlock()
{

}


/**********************************************************************
* TABMAPHeaderBlock::InitBlockFromData()
Expand Down Expand Up @@ -405,6 +425,8 @@ int TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
}
}

UpdatePrecision();

return 0;
}

Expand Down Expand Up @@ -444,6 +466,12 @@ int TABMAPHeaderBlock::Int2Coordsys(GInt32 nX, GInt32 nY,
else
dY = (nY - m_YDispl) / m_YScale;

// Round coordinates to the desired precision
if (m_XPrecision > 0 && m_YPrecision > 0)
{
dX = round(dX*m_XPrecision)/m_XPrecision;
dY = round(dY*m_YPrecision)/m_YPrecision;
}
//printf("Int2Coordsys: (%d, %d) -> (%.10g, %.10g)\n", nX, nY, dX, dY);

return 0;
Expand Down Expand Up @@ -664,6 +692,8 @@ int TABMAPHeaderBlock::SetCoordsysBounds(double dXMin, double dYMin,
m_nXMax = 1000000000;
m_nYMax = 1000000000;

UpdatePrecision();

return 0;
}

Expand Down Expand Up @@ -912,7 +942,6 @@ int TABMAPHeaderBlock::CommitToFile()
int TABMAPHeaderBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
int nFileOffset /* = 0*/)
{
int i;
/*-----------------------------------------------------------------
* Start with the default initialisation
*----------------------------------------------------------------*/
Expand All @@ -922,56 +951,7 @@ int TABMAPHeaderBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
/*-----------------------------------------------------------------
* Set acceptable default values for member vars.
*----------------------------------------------------------------*/
m_nMAPVersionNumber = HDR_VERSION_NUMBER;
m_nBlockSize = HDR_DATA_BLOCK_SIZE;

m_dCoordsys2DistUnits = 1.0;
m_nXMin = -1000000000;
m_nYMin = -1000000000;
m_nXMax = 1000000000;
m_nYMax = 1000000000;

m_nFirstIndexBlock = 0;
m_nFirstGarbageBlock = 0;
m_nFirstToolBlock = 0;

m_numPointObjects = 0;
m_numLineObjects = 0;
m_numRegionObjects = 0;
m_numTextObjects = 0;
m_nMaxCoordBufSize = 0;

m_nDistUnitsCode = 7; // Meters
m_nMaxSpIndexDepth = 0;
m_nCoordPrecision = 3; // ??? 3 digits of precision
m_nCoordOriginQuadrant = HDR_DEF_ORG_QUADRANT; // ??? N-E quadrant
m_nReflectXAxisCoord = HDR_DEF_REFLECTXAXIS;
m_nMaxObjLenArrayId = HDR_OBJ_LEN_ARRAY_SIZE-1; // See gabyObjLenArray[]
m_numPenDefs = 0;
m_numBrushDefs = 0;
m_numSymbolDefs = 0;
m_numFontDefs = 0;
m_numMapToolBlocks = 0;

m_sProj.nProjId = 0;
m_sProj.nEllipsoidId = 0;
m_sProj.nUnitsId = 7;
m_sProj.nDatumId = 0;
m_XScale = 1000.0; // Default coord range (before SetCoordSysBounds())
m_YScale = 1000.0; // will be [-1000000.000 .. 1000000.000]
m_XDispl = 0.0;
m_YDispl = 0.0;

for(i=0; i<6; i++)
m_sProj.adProjParams[i] = 0.0;

m_sProj.dDatumShiftX = 0.0;
m_sProj.dDatumShiftY = 0.0;
m_sProj.dDatumShiftZ = 0.0;
for(i=0; i<5; i++)
m_sProj.adDatumParams[i] = 0.0;

m_sProj.nAffineFlag = 0;
InitMembersWithDefaultValues();

/*-----------------------------------------------------------------
* And Set the map object length array in the buffer...
Expand All @@ -988,6 +968,17 @@ int TABMAPHeaderBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
return 0;
}

/**********************************************************************
* TABMAPHeaderBlock::UpdatePrecision()
*
* Update x and y maximum achievable precision given current scales
* (m_XScale and m_YScale)
**********************************************************************/
void TABMAPHeaderBlock::UpdatePrecision()
{
m_XPrecision = pow(10.0, round(log10(m_XScale)));
m_YPrecision = pow(10.0, round(log10(m_YScale)));
}

/**********************************************************************
* TABMAPHeaderBlock::Dump()
Expand Down
6 changes: 5 additions & 1 deletion gdal/ogr/ogrsf_frmts/mitab/mitab_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,9 @@ class TABRawBinBlock

class TABMAPHeaderBlock: public TABRawBinBlock
{
void InitMembersWithDefaultValues();
void UpdatePrecision();

protected:
TABProjInfo m_sProj;

Expand Down Expand Up @@ -955,7 +958,8 @@ class TABMAPHeaderBlock: public TABRawBinBlock
double m_YScale;
double m_XDispl;
double m_YDispl;

double m_XPrecision; // maximum achievable precision along X axis depending on bounds extent
double m_YPrecision; // maximum achievable precision along Y axis depending on bounds extent
};

/*---------------------------------------------------------------------
Expand Down

0 comments on commit 1580c26

Please sign in to comment.