void ShapeFileOptionsWidget::updateFieldValues() { for (QMap<QTreeWidgetItem*, Feature*>::iterator iter = mFeatures.begin(); iter != mFeatures.end(); ++iter) { QTreeWidgetItem* pItem = iter.key(); Feature* pFeature = iter.value(); if ((pItem != NULL) && (pFeature != NULL)) { vector<string> fieldNames = pFeature->getFieldNames(); for (vector<string>::iterator fieldIter = fieldNames.begin(); fieldIter != fieldNames.end(); ++fieldIter) { string name = *fieldIter; if (!name.empty()) { string type = pFeature->getFieldType(name); QString strValue; const DataVariant &var = pFeature->getFieldValue(name); strValue = QString::fromStdString(var.toDisplayString()); int iColumn = getColumn(QString::fromLatin1(name.c_str())); if (iColumn == -1) { addField(QString::fromLatin1(name.c_str()), QString::fromLatin1(type.c_str())); iColumn = getColumn(QString::fromLatin1(name.c_str())); } if (iColumn != -1) { pItem->setText(iColumn, strValue); } } } } } }
bool ShapeFile::save(Progress* pProgress, string& errorMessage) { errorMessage.clear(); int iFeatures = mFeatures.size(); if (iFeatures == 0) { errorMessage = "There are no features to save!"; if (pProgress != NULL) { pProgress->updateProgress(errorMessage, 0, ERRORS); } return false; } // Open the files int iType = -1; switch (mShape) { case ShapefileTypes::POINT_SHAPE: iType = SHPT_POINT; break; case ShapefileTypes::POLYLINE_SHAPE: iType = SHPT_ARC; break; case ShapefileTypes::POLYGON_SHAPE: iType = SHPT_POLYGON; break; case ShapefileTypes::MULTIPOINT_SHAPE: iType = SHPT_MULTIPOINT; break; default: errorMessage = "Can not save invalid shape type"; if (pProgress != NULL) { pProgress->updateProgress(errorMessage, 0, ERRORS); } return false; } QFileInfo fileInfo(QString::fromStdString(mFilename)); QDir fileDir = fileInfo.absoluteDir(); QString fileBaseName = fileDir.absoluteFilePath(fileInfo.completeBaseName()); std::string filename = fileBaseName.toStdString(); SHPHandle pShapeFile = SHPCreate(filename.c_str(), iType); if (pShapeFile == NULL) { errorMessage = "Cannot create the SHP and SHX files!"; if (pProgress != NULL) { pProgress->updateProgress(errorMessage, 0, ERRORS); } return false; } DBFHandle pAttributeFile = DBFCreate(filename.c_str()); if (pAttributeFile == NULL) { SHPClose(pShapeFile); errorMessage = "Cannot create the DBF file!"; if (pProgress != NULL) { pProgress->updateProgress(errorMessage, 0, ERRORS); } return false; } // Add the fields to the attribute file map<string, int> fieldIds; int iFields = mFields.size(); int i = 0; for (map<string, string>::iterator iter = mFields.begin(); iter != mFields.end(); ++iter, ++i) { if (pProgress != NULL) { pProgress->updateProgress("Writing fields...", i * 33 / iFields, NORMAL); } string name = iter->first; string type = iter->second; if (!name.empty()) { DBFFieldType eFieldType = FTInvalid; int iWidth = 0; int iDecimalPlaces = 0; if ((type == "char") || (type == "short") || (type == "int")) { eFieldType = FTInteger; iWidth = 18; } else if ((type == "float") || (type == "double")) { eFieldType = FTDouble; iWidth = 19; iDecimalPlaces = 8; } else if (type == "string") { eFieldType = FTString; iWidth = 254; } int iFieldId = DBFAddField(pAttributeFile, name.c_str(), eFieldType, iWidth, iDecimalPlaces); if (iFieldId != -1) { fieldIds[name] = iFieldId; } } } // Save the features and attributes for (i = 0; i < iFeatures; i++) { if (pProgress != NULL) { pProgress->updateProgress("Writing features...", 33 + (i * 67 / iFeatures), NORMAL); } Feature* pFeature = mFeatures[i]; if (pFeature != NULL) { // Features const vector<Feature::FeatureVertex>& vertices = pFeature->getVertices(); int iVertices = vertices.size(); vector<double> dX(iVertices); vector<double> dY(iVertices); vector<double> dZ(iVertices); for (int j = 0; j < iVertices; j++) { Feature::FeatureVertex vertex = vertices[j]; dX[j] = vertex.mX; dY[j] = vertex.mY; dZ[j] = vertex.mZ; } if (mShape == ShapefileTypes::POLYGON_SHAPE) { // make sure there are no collinear segments by calculating // the area of the triangle defined by each point triplet // if the area is 0, the points are collinear so we remove the // middle point and continue for (int a = 0; a < (iVertices - 2); a++) { int b = a + 1; int c = a + 2; double area = dX[a] * (dY[b] - dY[c]) + dX[b] * (dY[c] - dY[a]) + dX[c] * (dY[a] - dY[b]); if (fabs(area) < 1e-15) // equals zero { dX.erase(dX.begin() + b); dY.erase(dY.begin() + b); dZ.erase(dZ.begin() + b); a--; iVertices--; } } } SHPObject* pObject = SHPCreateObject(iType, i, 0, NULL, NULL, iVertices, &dX.front(), &dY.front(), &dZ.front(), NULL); if (pObject != NULL) { SHPRewindObject(pShapeFile, pObject); SHPWriteObject(pShapeFile, -1, pObject); SHPDestroyObject(pObject); } // Attributes for (map<string, int>::iterator iter = fieldIds.begin(); iter != fieldIds.end(); ++iter) { string name = iter->first; int iFieldId = iter->second; if (!name.empty()) { const DataVariant& var = pFeature->getFieldValue(name); if (var.isValid()) { string fieldType = pFeature->getFieldType(name); if (fieldType == var.getTypeName()) { if (fieldType == "int") { DBFWriteIntegerAttribute(pAttributeFile, i, iFieldId, dv_cast<int>(var)); } else if (fieldType == "double") { DBFWriteDoubleAttribute(pAttributeFile, i, iFieldId, dv_cast<double>(var)); } else if (fieldType == "string") { DBFWriteStringAttribute(pAttributeFile, i, iFieldId, dv_cast<string>(var).c_str()); } } } else { DBFWriteNULLAttribute(pAttributeFile, i, iFieldId); } } } } } SHPClose(pShapeFile); DBFClose(pAttributeFile); string prjFilename = filename + ".prj"; ofstream prjFile(prjFilename.c_str()); prjFile << prjFileContents; prjFile.close(); if (pProgress != NULL) { pProgress->updateProgress("Shape files saved!", 100, NORMAL); } return true; }