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);
               }
            }
         }
      }
   }
}
Exemple #2
0
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;
}