bool FeatureConnector::isForwardStartDirection(const BinaryIlwis3Table& topTable, qint32 colForward, qint32 colBackward, qint32 colCoords, long index) { qint32 fwl, bwl; double v; topTable.get(abs(index),colForward, v ); fwl = v; if ( fwl != iUNDEF) --fwl; // due to being raw values topTable.get(abs(index),colBackward, v ); bwl = v; if ( bwl != iUNDEF) --bwl; if ( abs(fwl) == abs(bwl) ) return true; if ( index < 0) return false; std::vector<Coordinate2d> startLine, forwardLine; topTable.get(abs(index), colCoords,startLine); topTable.get(abs(fwl), colCoords, forwardLine); bool forward = false; if ( fwl > 0) forward = startLine.back() == forwardLine.front(); else forward = startLine.back() == forwardLine.back(); return forward; }
bool FeatureConnector::isForwardStartDirection(const BinaryIlwis3Table& topTable, qint32 colForward, qint32 colBackward, qint32 colCoords, long index) { qint32 fwl, bwl; double v; topTable.get(abs(index) - 1,colForward, v ); fwl = v; // if ( fwl != iUNDEF) // --fwl; // due to being raw values topTable.get(abs(index)-1,colBackward, v ); bwl = v; // if ( bwl != iUNDEF) // --bwl; if ( abs(fwl) == abs(bwl) ) return true; if ( index < 0) return false; //qDebug() << fwl << bwl; std::vector<Coordinate> startLine, forwardLine; topTable.get(abs(index) - 1, colCoords,startLine); topTable.get(abs(fwl) - 1, colCoords, forwardLine); bool forward = false; if ( forwardLine.size() == 0 || startLine.size() == 0) throw ErrorObject(TR("aborting topoplogy reading, polygon might be corrupted")); if ( fwl > 0) forward = startLine.back() == forwardLine.front(); else forward = startLine.back() == forwardLine.back(); return forward; }
bool FeatureConnector::loadBinaryPolygons30(FeatureCoverage *fcoverage, ITable& tbl) { BinaryIlwis3Table polTable; if ( !polTable.load(_odf)) { return ERROR1(ERR_COULD_NOT_OPEN_READING_1,_odf->url()) ; } BinaryIlwis3Table topTable; if ( !topTable.load(_odf,"top")) { return ERROR1(ERR_COULD_NOT_OPEN_READING_1,_odf->url()) ; } qint32 colValue = polTable.index("PolygonValue"); qint32 colTopStart = polTable.index("TopStart"); qint32 colArea = polTable.index("Area"); int nrPolygons = polTable.rows(); bool isNumeric = _odf->value("BaseMap","Range") != sUNDEF; fcoverage->setFeatureCount(itFEATURE, iUNDEF, FeatureInfo::ALLFEATURES); // reset all counts double v; map<quint32,vector<geos::geom::Geometry *>> polygons; std::vector<double> featureValues(isNumeric ? nrPolygons : 0); for(int i = 0; i < nrPolygons; ++i) { polTable.get(i,colArea, v); if ( v < 0) continue; polTable.get(i,colTopStart,v); qint32 index = v; std::vector<geos::geom::LinearRing *> *rings = new std::vector<geos::geom::LinearRing *>(); if (getRings(fcoverage,index, topTable, polTable, rings)) { if ( rings->size() == 0) continue; geos::geom::LinearRing *outer = rings->front(); vector<geos::geom::Geometry *> *inners = new vector<geos::geom::Geometry *>(rings->size() - 1); for(int j=1; j < rings->size(); ++j) { (*inners)[j-1] = rings->at(j); } geos::geom::Polygon *pol = fcoverage->geomfactory()->createPolygon(outer, inners); //collect all polygons in a map; the key is either a unique number ( index j) or the raw value from the polygon //in this way all polygons with the same raw value will become a multipolygon double value; polTable.get(i, colValue, value); if (value == rUNDEF || value == iILW3UNDEF || value == shILW3UNDEF) continue; polygons[isNumeric ? i + 1 : (quint32)value].push_back(pol); if ( isNumeric) { featureValues[i] = value; } } } addFeatures(polygons, fcoverage,featureValues, itPOLYGON); return true; }
bool FeatureConnector::getRings(qint32 startIndex, const BinaryIlwis3Table& topTable, const BinaryIlwis3Table& polTable, std::vector<vector<Coordinate2d>>& rings ){ qint32 row = startIndex; qint32 colCoords = topTable.index("Coords"); qint32 colForward = topTable.index("ForwardLink"); qint32 colBackward = topTable.index("BackwardLink"); std::vector<Coordinate> ring; bool forward = isForwardStartDirection(topTable,colForward, colBackward, colCoords, row); do{ std::vector<Coordinate> coords; topTable.get(row,colCoords,coords); if( coords.size() == 0 ||coords.back() == coords.front()){ ring.resize(coords.size()); std::copy(coords.begin(), coords.end(), ring.begin()); } else if ( coords.back() == ring.back()) { ring.resize(coords.size()); std::reverse_copy(coords.begin(), coords.end(), ring.begin()); } else if ( ring.front() == coords.front()) { ring.resize(coords.size()); std::reverse_copy(coords.begin(), coords.end(), ring.begin()); } else if ( ring.front() == coords.back()) { ring.resize(coords.size()); std::copy(coords.begin(), coords.end(), ring.begin()); } if ( ring.front() == ring.back() && ring.size() > 3) { std::vector<Coordinate2d> ring2d; Coordinate crdOld; for(const Coordinate& crd : ring) { if ( crd == crdOld) // remove duplicates continue; ring2d.push_back(crd); crdOld = crd; } rings.push_back(ring2d); coords.clear(); ring.clear(); } qint32 oldIndex = row; double v; if ( forward) topTable.get(abs(row),colForward,v); else topTable.get(abs(row), colBackward, v);\ row = v; if ( oldIndex == row && row != startIndex) // this would indicate infintite loop. corrupt data return false; forward = row > 0; } while(abs(row) != abs(startIndex) && row != iUNDEF); return true; }
bool FeatureConnector::loadBinaryPolygons30(FeatureCoverage *fcoverage, ITable& tbl) { BinaryIlwis3Table polTable; if ( !polTable.load(_odf)) { return ERROR1(ERR_COULD_NOT_OPEN_READING_1,_odf->fileinfo().fileName()) ; } BinaryIlwis3Table topTable; if ( !topTable.load(_odf,"top")) { return ERROR1(ERR_COULD_NOT_OPEN_READING_1,_odf->fileinfo().fileName()) ; } qint32 colValue = polTable.index("PolygonValue"); qint32 colTopStart = polTable.index("TopStart"); qint32 colArea = polTable.index("Area"); int nrPolygons = polTable.rows(); bool isNumeric = _odf->value("BaseMap","Range") != sUNDEF; double v; for(int i = 0; i < nrPolygons; ++i) { polTable.get(i,colArea, v); if ( v < 0) continue; polTable.get(i,colTopStart,v); qint32 index = v; std::vector<std::vector<Coordinate2d>> rings; if (getRings(index, topTable, polTable, rings)) { if ( rings.size() == 0) continue; Polygon polygon; polygon.outer().resize(rings[0].size()); std::copy(rings[0].begin(), rings[0].end(), polygon.outer().begin()); for(int j = 1; j < rings.size(); ++j) { polygon.inners()[j-1].resize(rings[j].size()); std::copy(rings[j].begin(), rings[j].end(), polygon.inners()[j-1].begin()); } polTable.get(i, colValue, v); if ( isNumeric) { tbl->cell(COVERAGEKEYCOLUMN, i, QVariant(i)); tbl->cell(FEATUREVALUECOLUMN, i, QVariant(v)); fcoverage->newFeature({polygon}); } else { quint32 itemId = v; tbl->cell(COVERAGEKEYCOLUMN, i, QVariant(itemId)); SPFeatureI feature = fcoverage->newFeature({polygon}); tbl->cell(FEATUREIDCOLUMN, i, QVariant(feature->featureid())); } } } return true; }
bool GeorefConnector::loadGeorefTiepoints(const IniFile& odf, GeoReference *grf) { QString csyName = odf.value("GeoRef","CoordSystem"); QUrl path = mastercatalog()->name2url(csyName, itCOORDSYSTEM); ICoordinateSystem csy; if(!csy.prepare(path.toString())) { return ERROR2(ERR_COULD_NOT_LOAD_2, "coordinate system",csyName); } grf->coordinateSystem(csy); QSharedPointer<PlanarCTPGeoReference> grfctp(grf->as<PlanarCTPGeoReference>()); BinaryIlwis3Table tbl; tbl.load(_odf); std::vector<int> colindexes(10, iUNDEF); enum ColIndexID{ciiX=0, ciiY=1, ciiZ=2, ciiLAT=3, ciiLON=4, ciiXP=5, ciiYP=6, ciiACT=7, ciiDX=8, ciiDY=9, ciiNEVER=10}; colindexes[ciiX] = tbl.index("X"); colindexes[ciiY] = tbl.index("Y"); colindexes[ciiZ] = tbl.index("Z"); colindexes[ciiXP] = tbl.index("Col"); colindexes[ciiYP] = tbl.index("Row"); colindexes[ciiACT] = tbl.index("Active"); //colindexes[ciiDX] = tbl.index("DCol"); //colindexes[ciiDY] = tbl.index("DRow"); for(int rec = 0; rec < tbl.rows(); ++rec){ double x=rUNDEF; tbl.get(rec,colindexes[ciiX],x); double y=rUNDEF; tbl.get(rec,colindexes[ciiY],y); double z=0; if (colindexes[ciiZ] != iUNDEF) { tbl.get(rec,colindexes[ciiZ],z); } double xp=rUNDEF; tbl.get(rec,colindexes[ciiXP],xp); double yp=rUNDEF; tbl.get(rec,colindexes[ciiYP],yp); double active=1; tbl.get(rec,colindexes[ciiACT],active); ControlPoint ctp(Coordinate(x,y,z),Pixeld(xp,yp)); ctp.active(active != 0); grfctp->setControlPoint(ctp); } QString transf = odf.value("GeoRefCTP", "Transformation"); PlanarCTPGeoReference::Transformation transformation; if (transf == "Conform") transformation = PlanarCTPGeoReference::tCONFORM; else if (transf == "Affine") transformation = PlanarCTPGeoReference::tAFFINE; else if (transf == "SecondOrder") transformation = PlanarCTPGeoReference::tSECONDORDER; else if (transf == "FullSecondOrder") transformation = PlanarCTPGeoReference::tFULLSECONDORDER; else if (transf == "ThirdOrder") transformation = PlanarCTPGeoReference::tTHIRDORDER; else if (transf == "Projective") transformation = PlanarCTPGeoReference::tPROJECTIVE; grfctp->transformation(transformation); grfctp->compute(); return true; }
bool FeatureConnector::loadBinarySegments(FeatureCoverage *fcoverage) { BinaryIlwis3Table mpsTable; if ( !mpsTable.load(_odf)) { return ERROR1(ERR_COULD_NOT_OPEN_READING_1,_odf->fileinfo().fileName()) ; } int colCoords = mpsTable.index("Coords"); int colItemId = mpsTable.index("SegmentValue"); bool isNumeric = _odf->value("BaseMap","Range") != sUNDEF; ITable tbl = fcoverage->attributeTable(); // if ( isNumeric) // in other case nr of record already has been set as it is based on a real table // tbl->setRows(mpsTable.rows()); double value; for(quint32 i= 0; i < mpsTable.rows(); ++i) { std::vector<Coordinate > coords; mpsTable.get(i,colCoords,coords); Line2D<Coordinate2d > line; line.resize(coords.size()); std::copy(coords.begin(), coords.end(), line.begin()); mpsTable.get(i, colItemId,value); if ( isNumeric) { tbl->cell(COVERAGEKEYCOLUMN, i, QVariant(i)); tbl->cell(FEATUREVALUECOLUMN, i, QVariant(value)); SPFeatureI feature = fcoverage->newFeature({line}); tbl->cell(FEATUREIDCOLUMN, i, QVariant(feature->featureid())); } else { quint32 itemId = value; tbl->cell(COVERAGEKEYCOLUMN, i, QVariant(itemId)); SPFeatureI feature = fcoverage->newFeature({line}); tbl->cell(FEATUREIDCOLUMN, i, QVariant(feature->featureid())); } } return true; }
bool FeatureConnector::loadBinaryPoints(FeatureCoverage *fcoverage) { BinaryIlwis3Table mppTable; if ( !mppTable.load(_odf)) { return ERROR1(ERR_COULD_NOT_OPEN_READING_1,_odf->url()) ; } // two cases; the old case; 2 columns for x and y. and the new case one column for coord int coordColumnX = mppTable.index("x"); int coordColumnY = mppTable.index("y"); int coordColumn = mppTable.index("Coordinate"); int colItemId = mppTable.index("Name"); bool isNumeric = _odf->value("BaseMap","Range") != sUNDEF; std::vector<double> featureValues(isNumeric ? mppTable.rows() : 0); bool newCase = coordColumnX == iUNDEF; fcoverage->setFeatureCount(itFEATURE, iUNDEF, FeatureInfo::ALLFEATURES); // reset all counts map<quint32,vector<geos::geom::Geometry *>> points; for(quint32 i= 0; i < mppTable.rows(); ++i) { Coordinate c; double value; if ( newCase) { mppTable.get(i, coordColumn, c); } else { double x,y; mppTable.get(i, coordColumnX, x); mppTable.get(i, coordColumnY, y); c = Coordinate(x,y); } mppTable.get(i, colItemId,value); geos::geom::Point *point = fcoverage->geomfactory()->createPoint(c); points[isNumeric ? i + 1 : (quint32)value].push_back(point); if ( isNumeric) { featureValues[i] = value; } } addFeatures(points, fcoverage,featureValues, itPOINT); return true; }
bool FeatureConnector::loadBinaryPoints(FeatureCoverage *fcoverage) { BinaryIlwis3Table mppTable; if ( !mppTable.load(_odf)) { return ERROR1(ERR_COULD_NOT_OPEN_READING_1,_odf->fileinfo().fileName()) ; } // two cases; the old case; 2 columns for x and y. and the new case one column for coord int coordColumnX = mppTable.index("x"); int coordColumnY = mppTable.index("y"); int coordColumn = mppTable.index("Coordinate"); int colItemId = mppTable.index("Name"); ITable tbl = fcoverage->attributeTable(); bool newCase = coordColumnX == iUNDEF; for(quint32 i= 0; i < mppTable.rows(); ++i) { Coordinate c; double itemIdT; if ( newCase) { mppTable.get(i, coordColumn, c); } else { double x,y; mppTable.get(i, coordColumnX, x); mppTable.get(i, coordColumnY, y); c = Coordinate(x,y); } mppTable.get(i, colItemId,itemIdT); quint32 itemId = itemIdT; tbl->cell(COVERAGEKEYCOLUMN, i, QVariant(itemId)); SPFeatureI feature = fcoverage->newFeature({c}); tbl->cell(FEATUREIDCOLUMN, i, QVariant(feature->featureid())); } return true; }
bool FeatureConnector::loadBinarySegments(FeatureCoverage *fcoverage) { BinaryIlwis3Table mpsTable; if ( !mpsTable.load(_odf)) { return ERROR1(ERR_COULD_NOT_OPEN_READING_1,_odf->url()) ; } int colCoords = mpsTable.index("Coords"); int colItemId = mpsTable.index("SegmentValue"); bool isNumeric = _odf->value("BaseMap","Range") != sUNDEF; fcoverage->setFeatureCount(itFEATURE, iUNDEF, FeatureInfo::ALLFEATURES); // reset all counts map<quint32,vector<geos::geom::Geometry *>> lines; std::vector<double> featureValues(isNumeric ? mpsTable.rows() : 0); double value; for(quint32 i= 0; i < mpsTable.rows(); ++i) { std::vector<Coordinate > coords; mpsTable.get(i,colCoords,coords); geos::geom::CoordinateArraySequence *vertices = new geos::geom::CoordinateArraySequence(coords.size()); for(int i=0; i < coords.size(); ++i) vertices->setAt(geos::geom::Coordinate(coords[i].x, coords[i].y, coords[i].z), i); geos::geom::LineString *line = fcoverage->geomfactory()->createLineString(vertices); mpsTable.get(i, colItemId,value); //collect all lines in a map; the key is either a unique number ( index j) or the raw value from the line //in this way all lines with the same raw value will become a multilinestring lines[isNumeric ? i + 1 : (quint32)value].push_back(line); if ( isNumeric) { featureValues[i] = value; } } addFeatures(lines, fcoverage,featureValues, itLINE); return true; }
bool FeatureConnector::getRings(FeatureCoverage *fcoverage, qint32 startIndex, const BinaryIlwis3Table& topTable, const BinaryIlwis3Table& polTable, std::vector<geos::geom::LinearRing *> *rings ){ qint32 row = startIndex; qint32 colCoords = topTable.index("Coords"); qint32 colForward = topTable.index("ForwardLink"); qint32 colBackward = topTable.index("BackwardLink"); bool outerIsCCW = true; std::vector<geos::geom::Coordinate> *ring = new std::vector<geos::geom::Coordinate>(); bool forward = isForwardStartDirection(topTable,colForward, colBackward, colCoords, row); do{ std::vector<Coordinate> coords; topTable.get(abs(row) - 1,colCoords,coords); int ringsize = (int)ring->size(); ring->reserve(ring->size() + coords.size()); if( ringsize == 0 ||coords.front() == ring->back()){ for(int i = 0; i < coords.size() ; ++i){ if ( ring->size() > 0 && ring->back() == coords[i]) continue; ring->push_back(coords[i]); } } else if ( ring->size() > 0 && coords.back() == ring->back()) { for(int i = 0; i < coords.size() ; ++i){ const auto& crd = coords[coords.size() - i - 1]; if ( ring->back() == crd) continue; ring->push_back(crd); } } else if ( ring->size() > 0 && ring->front() == coords.front()) { for(int i = 0; i < coords.size() ; ++i) ring->push_back(coords[i]); } else if ( ring->size() > 0 && ring->front() == coords.back()) { for(int i = 0; i < coords.size() ; ++i) ring->push_back(coords[i]); } if ( ring->size() > 3 && ring->front() == ring->back()) { ring->shrink_to_fit(); geos::geom::CoordinateArraySequence * ringIn = new geos::geom::CoordinateArraySequence(ring); ringIn->removeRepeatedPoints(); if ( rings->size() == 0) { outerIsCCW = geos::algorithm::CGAlgorithms::isCCW(ringIn); }else { bool isCCW = geos::algorithm::CGAlgorithms::isCCW(ringIn); if ( outerIsCCW && isCCW){ // holes must have a different turning direction geos::geom::CoordinateSequence::reverse(ringIn); } } rings->push_back( fcoverage->geomfactory()->createLinearRing(ringIn)); ring = new std::vector<geos::geom::Coordinate>(); } qint32 oldIndex = row; double v; if ( forward) topTable.get(abs(row) - 1,colForward,v); else topTable.get(abs(row) - 1, colBackward, v);\ row = v; if ( oldIndex == row && row != startIndex) // this would indicate infintite loop. corrupt data return false; forward = row > 0; } while(abs(row) != abs(startIndex) && row != iUNDEF); return true; }