From b17cdbd02dc3c6f09ee3686b8e9bc68e062d7d9f Mon Sep 17 00:00:00 2001 From: Petros Koutsolampros <2184600+pklampros@users.noreply.github.com> Date: Wed, 15 Jul 2020 23:05:37 +0300 Subject: [PATCH 1/2] Test MapInfo .mif/.mid for null-filled columns --- salaTest/testmapinfodata.cpp | 49 ++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/salaTest/testmapinfodata.cpp b/salaTest/testmapinfodata.cpp index 8fe2cfbd..95a87e57 100644 --- a/salaTest/testmapinfodata.cpp +++ b/salaTest/testmapinfodata.cpp @@ -82,6 +82,55 @@ TEST_CASE("MapInfo failing column attribute columns", "") REQUIRE_FALSE(mapinfodata.readcolumnheaders(mifstream, columnheads)); } +TEST_CASE("MapInfo MID file with empty column", "") +{ + const float EPSILON = 0.001; + + // A typical MIF + + std::string mifdata = + "Version 300\n" \ + "Charset \"WindowsLatin1\"\n" \ + "Delimiter \",\"\n" \ + "Index 1,2,3,4\n" \ + "CoordSys Earth Projection 8, 79, \"m\", -2, 49, 0.9996012717, 400000, -100000\n"; + + mifdata += + "Columns 4\n" \ + " ID Integer\n" \ + " Length_m Float\n" \ + " Height_m Float\n" \ + " Width_m Float\n" \ + "Data\n" \ + "\n" \ + "Line 534014.29 182533.33 535008.52 182764.11\n" \ + " Pen (1,2,0)\n" \ + "Line 533798.68 183094.69 534365.48 183159.01\n" \ + " Pen (1,2,0)\n" \ + "Point 534014.29 182533.33\n" \ + " Symbol (34,0,12)"; + + + // A MID with empty columns + + std::string middata = + "1,1017.81,,\n" \ + "2,568.795,,\n" \ + "3,216.026,,"; + + ShapeMap shapeMap("MapInfoTest"); + MapInfoData mapinfodata; + + std::stringstream mifstream(mifdata); + std::stringstream midstream(middata); + REQUIRE(mapinfodata.import(mifstream, midstream, shapeMap) == MINFO_OK); + REQUIRE(shapeMap.getAttributeTable().getNumColumns() == 4); + REQUIRE(shapeMap.getAttributeTable().getColumn(0).getName() == "Id"); + REQUIRE(shapeMap.getAttributeTable().getColumn(1).getName() == "Length_M"); + REQUIRE(shapeMap.getAttributeTable().getColumn(2).getName() == "Height_M"); + REQUIRE(shapeMap.getAttributeTable().getColumn(3).getName() == "Width_M"); +} + TEST_CASE("Complete proper MapInfo file", "") { const float EPSILON = 0.001; From 19dce0f1b032a3be0827614fb24498b97aae753a Mon Sep 17 00:00:00 2001 From: Petros Koutsolampros <2184600+pklampros@users.noreply.github.com> Date: Wed, 15 Jul 2020 23:14:01 +0300 Subject: [PATCH 2/2] Make sure null columns in .mid files get a value on import --- salaTest/testmapinfodata.cpp | 37 ++++++++++++++++++++++++++++----- salalib/parsers/mapinfodata.cpp | 13 +++++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/salaTest/testmapinfodata.cpp b/salaTest/testmapinfodata.cpp index 95a87e57..4dddf9b2 100644 --- a/salaTest/testmapinfodata.cpp +++ b/salaTest/testmapinfodata.cpp @@ -124,11 +124,38 @@ TEST_CASE("MapInfo MID file with empty column", "") std::stringstream mifstream(mifdata); std::stringstream midstream(middata); REQUIRE(mapinfodata.import(mifstream, midstream, shapeMap) == MINFO_OK); - REQUIRE(shapeMap.getAttributeTable().getNumColumns() == 4); - REQUIRE(shapeMap.getAttributeTable().getColumn(0).getName() == "Id"); - REQUIRE(shapeMap.getAttributeTable().getColumn(1).getName() == "Length_M"); - REQUIRE(shapeMap.getAttributeTable().getColumn(2).getName() == "Height_M"); - REQUIRE(shapeMap.getAttributeTable().getColumn(3).getName() == "Width_M"); + + AttributeTable& att = shapeMap.getAttributeTable(); + + REQUIRE(att.getNumColumns() == 4); + REQUIRE(att.getColumn(0).getName() == "Id"); + REQUIRE(att.getColumn(1).getName() == "Length_M"); + REQUIRE(att.getColumn(2).getName() == "Height_M"); + REQUIRE(att.getColumn(3).getName() == "Width_M"); + + std::map shapes = shapeMap.getAllShapes(); + auto shapeRef0 = depthmapX::getMapAtIndex(shapes, 0); + auto shapeRef1 = depthmapX::getMapAtIndex(shapes, 1); + auto shapeRef2 = depthmapX::getMapAtIndex(shapes, 2); + + REQUIRE(att.getNumRows() == 3); + auto &row0 = att.getRow(AttributeKey(shapeRef0->first)); + auto &row1 = att.getRow(AttributeKey(shapeRef1->first)); + auto &row2 = att.getRow(AttributeKey(shapeRef2->first)); + + REQUIRE(row0.getValue("Id") == 1); + REQUIRE(row1.getValue("Id") == 2); + REQUIRE(row2.getValue("Id") == 3); + REQUIRE(row0.getValue("Length_M") == Approx(1017.81).epsilon(EPSILON)); + REQUIRE(row1.getValue("Length_M") == Approx(568.795).epsilon(EPSILON)); + REQUIRE(row2.getValue("Length_M") == Approx(216.026).epsilon(EPSILON)); + REQUIRE(row0.getValue("Height_M") == -1); + REQUIRE(row1.getValue("Height_M") == -1); + REQUIRE(row2.getValue("Height_M") == -1); + REQUIRE(row0.getValue("Width_M") == -1); + REQUIRE(row1.getValue("Width_M") == -1); + REQUIRE(row2.getValue("Width_M") == -1); + } TEST_CASE("Complete proper MapInfo file", "") diff --git a/salalib/parsers/mapinfodata.cpp b/salalib/parsers/mapinfodata.cpp index f4b011eb..2ea43f5a 100644 --- a/salalib/parsers/mapinfodata.cpp +++ b/salalib/parsers/mapinfodata.cpp @@ -191,10 +191,17 @@ int MapInfoData::import(std::istream& miffile, std::istream& midfile, ShapeMap& int length = (here < line.length()) ? here-first-1 : here-first; std::string field = line.substr(first,length); first = here; - if (reading == readable[nextreadable]) { - float val = stof(field); + if (length == 1 && field[0] == m_delimiter) { + // field is empty + row.setValue(colindexes[nextreadable], -1); + nextreadable++; // go to next column + } else if (reading == readable[nextreadable]) { + float val = -1; + if(!field.empty()) { + val = stof(field); + } row.setValue(colindexes[nextreadable],val); - nextreadable++; + nextreadable++; // go to next column } reading++; }