vector<Feature*> ShapeFile::addFeatures(GraphicElement* pGraphicElement, GraphicObject* pObject, RasterElement* pGeoref, string& message) { vector<Feature*> features; message.clear(); if (pGraphicElement == NULL) { message = "Features cannot be added because the data element is invalid!"; return features; } if (pGeoref == NULL || !pGeoref->isGeoreferenced()) { message = "No georeferencing information can be found."; return features; } // Do not allow erase or toggle objects if (pObject != NULL) { if (pObject->getDrawMode() != DRAW) { message = "The " + pObject->getName() + " object is an erase or toggle object, so a feature " "will not be added."; return features; } } // Get the objects list<GraphicObject*> objects; if (pObject != NULL) { objects.push_back(pObject); } else { GraphicGroup* pGroup = pGraphicElement->getGroup(); if (pGroup != NULL) { // If the element is displayed in an annotation layer, use the selected objects AnnotationLayer* pAnnotationLayer = dynamic_cast<AnnotationLayer*>(pGroup->getLayer()); if (pAnnotationLayer != NULL) { pAnnotationLayer->getSelectedObjects(objects); } if (objects.empty()) { objects = pGroup->getObjects(); } } } // Create the features string elementName = pGraphicElement->getName(); const DynamicObject* pMetadata = getSourceMetadata(*pGraphicElement); switch (mShape) { case ShapefileTypes::POINT_SHAPE: { if (dynamic_cast<AnnotationElement*>(pGraphicElement) != NULL) { if (objects.empty()) { message = "Cannot create a shape file from an empty element."; return features; } // Get names of attributes which should be copied/exported. vector<string> attrNames; const DynamicObject* pAttributeMetadata = getSourceAttributeMetadata(*pGraphicElement); if (pAttributeMetadata != NULL) { pAttributeMetadata->getAttributeNames(attrNames); } for (list<GraphicObject*>::const_iterator it = objects.begin(); it != objects.end(); ++it) { GraphicObject* pCurrentObject = *it; if (pCurrentObject != NULL) { // Do not allow erase or toggle objects if (pCurrentObject->getDrawMode() != DRAW) { continue; } string objectName = pCurrentObject->getName(); vector<LocationType> vertices; pCurrentObject->getRotatedExtents(vertices); // Each point created from this object uses the same metadata. int idx = -1; if (pMetadata != NULL) { idx = getAttributeIndex(*pCurrentObject, *pMetadata); } LocationType pixel; for (vector<LocationType>::const_iterator verticesIter = vertices.begin(); verticesIter != vertices.end(); ++verticesIter) { // Add the feature SessionItem* pSessionItem = pGraphicElement; if (pObject != NULL) { pSessionItem = pObject; } Feature* pFeature = new Feature(pSessionItem); features.push_back(pFeature); mFeatures.push_back(pFeature); VERIFYNR(pFeature->attach(SIGNAL_NAME(Subject, Modified), Slot(this, &ShapeFile::shapeModified))); // Fields pFeature->addField("Name", string()); if (!elementName.empty()) { if (pObject != NULL) { pFeature->setFieldValue("Name", elementName + ": " + pObject->getName()); } else { pFeature->setFieldValue("Name", elementName + ": " + objectName); } } pixel.mX = verticesIter->mX + 0.5; pixel.mY = verticesIter->mY + 0.5; QString pixelName = "(" + QString::number(verticesIter->mX + 1) + ", " + QString::number(verticesIter->mY + 1) + ")"; pFeature->setFieldValue("Pixel", pixelName.toStdString()); if (idx > -1 && pAttributeMetadata != NULL) { copyMetadata(attrNames, idx, *pAttributeMetadata, *pFeature); } LocationType geo = pGeoref->convertPixelToGeocoord(*verticesIter); pFeature->addVertex(geo.mY, geo.mX); } } } } else { // The BitMaskIterator does not support negative extents and // the BitMask does not correctly handle the outside flag so // the BitMaskIterator is used for cases when the outside flag is true and // the BitMask is used for cases when the outside flag is false AoiElement* pAoiElement = dynamic_cast<AoiElement*>(pGraphicElement); VERIFYRV(pAoiElement != NULL, features); const BitMask* pMask = pAoiElement->getSelectedPoints(); if (pObject != NULL) { pMask = pObject->getPixels(); if (pMask == NULL) { message = "The " + pObject->getName() + " object cannot be represented by the " + StringUtilities::toDisplayString(mShape) + " shape type, so a feature will not be added."; return features; } } if (pMask != NULL) { BitMaskIterator maskIt(pMask, pGeoref); if ((maskIt.getCount() > 0 && pMask->isOutsideSelected() == true) || (pMask->getCount() > 0 && pMask->isOutsideSelected() == false)) { // Add features for each selected pixel int startColumn = 0; int endColumn = 0; int startRow = 0; int endRow = 0; if (pMask->isOutsideSelected() == true) { maskIt.getBoundingBox(startColumn, startRow, endColumn, endRow); } else { pMask->getBoundingBox(startColumn, startRow, endColumn, endRow); } LocationType pixel; for (int i = startColumn; i <= endColumn; i++) { for (int j = startRow; j <= endRow; j++) { if ((maskIt.getPixel(i, j) && pMask->isOutsideSelected() == true) || (pMask->getPixel(i, j) && pMask->isOutsideSelected() == false)) { // Add the feature SessionItem* pSessionItem = pGraphicElement; if (pObject != NULL) { pSessionItem = pObject; } Feature* pFeature = new Feature(pSessionItem); features.push_back(pFeature); mFeatures.push_back(pFeature); VERIFYNR(pFeature->attach(SIGNAL_NAME(Subject, Modified), Slot(this, &ShapeFile::shapeModified))); pixel.mX = i + 0.5; pixel.mY = j + 0.5; // Fields pFeature->addField("Name", string()); pFeature->addField("Pixel", string()); if (!elementName.empty()) { if (pObject != NULL) { pFeature->setFieldValue("Name", elementName + ": " + pObject->getName()); } else { pFeature->setFieldValue("Name", elementName); } } QString pixelName = "(" + QString::number(i + 1) + ", " + QString::number(j + 1) + ")"; pFeature->setFieldValue("Pixel", pixelName.toStdString()); // Vertex pixel = pGeoref->convertPixelToGeocoord(pixel); pFeature->addVertex(pixel.mY, pixel.mX); // Longitude as x-coord } } } } } } } break; case ShapefileTypes::POLYLINE_SHAPE: { if (objects.empty()) { message = "Cannot create a shape file from an empty element."; return features; } // Get names of attributes which should be copied/exported. vector<string> attrNames; const DynamicObject* pAttributeMetadata = getSourceAttributeMetadata(*pGraphicElement); if (pAttributeMetadata != NULL) { pAttributeMetadata->getAttributeNames(attrNames); } for (list<GraphicObject*>::const_iterator it = objects.begin(); it != objects.end(); ++it) { GraphicObject* pCurrentObject = *it; if (pCurrentObject != NULL) { GraphicObjectType objectType = pCurrentObject->getGraphicObjectType(); if ((objectType == LINE_OBJECT) || (objectType == POLYLINE_OBJECT) || (objectType == HLINE_OBJECT) || (objectType == VLINE_OBJECT)) { // Do not allow erase or toggle objects if (pCurrentObject->getDrawMode() != DRAW) { continue; } string objectName = pCurrentObject->getName(); vector<LocationType> vertices; pCurrentObject->getRotatedExtents(vertices); if (vertices.empty() == false) { Feature* pFeature = new Feature(pCurrentObject); features.push_back(pFeature); mFeatures.push_back(pFeature); VERIFYNR(pFeature->attach(SIGNAL_NAME(Subject, Modified), Slot(this, &ShapeFile::shapeModified))); pFeature->addField("Name", string()); if (!elementName.empty()) { pFeature->setFieldValue("Name", elementName + ": " + objectName); } // Copy attributes. if ((pMetadata != NULL) && (pAttributeMetadata != NULL)) { int idx = getAttributeIndex(*pCurrentObject, *pMetadata); if (idx > -1) { copyMetadata(attrNames, idx, *pAttributeMetadata, *pFeature); } } for (vector<LocationType>::const_iterator iter = vertices.begin(); iter != vertices.end(); ++iter) { LocationType geo = pGeoref->convertPixelToGeocoord(*iter); pFeature->addVertex(geo.mY, geo.mX); } } } } } } break; case ShapefileTypes::POLYGON_SHAPE: { if (objects.empty()) { message = "Cannot create a shape file from an empty element."; return features; } // Get names of attributes which should be copied/exported. vector<string> attrNames; const DynamicObject* pAttributeMetadata = getSourceAttributeMetadata(*pGraphicElement); if (pAttributeMetadata != NULL) { pAttributeMetadata->getAttributeNames(attrNames); } for (list<GraphicObject*>::const_iterator it = objects.begin(); it != objects.end(); ++it) { GraphicObject* pCurrentObject = *it; if (pCurrentObject != NULL) { GraphicObjectType objectType = pCurrentObject->getGraphicObjectType(); if ((objectType == RECTANGLE_OBJECT) || (objectType == ROUNDEDRECTANGLE_OBJECT) || (objectType == ELLIPSE_OBJECT) || (objectType == TRIANGLE_OBJECT) || (objectType == POLYGON_OBJECT) || (objectType == ARC_OBJECT)) { // Do not allow erase or toggle objects if (pCurrentObject->getDrawMode() != DRAW) { continue; } string objectName = pCurrentObject->getName(); vector<LocationType> vertices; pCurrentObject->getRotatedExtents(vertices); if (vertices.empty() == false) { // To represent non-polygon objects as polygons, add the first vertex as the last vertex if (objectType != POLYGON_OBJECT) { vertices.push_back(vertices.front()); } Feature* pFeature = new Feature(pCurrentObject); features.push_back(pFeature); mFeatures.push_back(pFeature); VERIFYNR(pFeature->attach(SIGNAL_NAME(Subject, Modified), Slot(this, &ShapeFile::shapeModified))); pFeature->addField("Name", string()); if (!elementName.empty()) { pFeature->setFieldValue("Name", elementName + ": " + objectName); } // Copy attributes. if ((pMetadata != NULL) && (pAttributeMetadata != NULL)) { int idx = getAttributeIndex(*pCurrentObject, *pMetadata); if (idx > -1) { copyMetadata(attrNames, idx, *pAttributeMetadata, *pFeature); } } for (vector<LocationType>::const_iterator iter = vertices.begin(); iter != vertices.end(); ++iter) { LocationType geo = pGeoref->convertPixelToGeocoord(*iter); pFeature->addVertex(geo.mY, geo.mX); } } } } } } break; case ShapefileTypes::MULTIPOINT_SHAPE: { if (dynamic_cast<AnnotationElement*>(pGraphicElement) != NULL) { if (objects.empty()) { message = "Cannot create a shape file from an empty element."; return features; } // Get names of attributes which should be copied/exported. vector<string> attrNames; const DynamicObject* pAttributeMetadata = getSourceAttributeMetadata(*pGraphicElement); if (pAttributeMetadata != NULL) { pAttributeMetadata->getAttributeNames(attrNames); } for (list<GraphicObject*>::const_iterator it = objects.begin(); it != objects.end(); ++it) { GraphicObject* pCurrentObject = *it; if (pCurrentObject != NULL) { // Do not allow erase or toggle objects if (pCurrentObject->getDrawMode() != DRAW) { continue; } Feature* pFeature = new Feature(pGraphicElement); features.push_back(pFeature); mFeatures.push_back(pFeature); VERIFYNR(pFeature->attach(SIGNAL_NAME(Subject, Modified), Slot(this, &ShapeFile::shapeModified))); // Fields pFeature->addField("Name", string()); if (!elementName.empty()) { if (pObject != NULL) { pFeature->setFieldValue("Name", elementName + ": " + pObject->getName()); } else { pFeature->setFieldValue("Name", elementName); } } // Copy attributes. if ((pMetadata != NULL) && (pAttributeMetadata != NULL)) { int idx = getAttributeIndex(*pCurrentObject, *pMetadata); if (idx > -1) { copyMetadata(attrNames, idx, *pAttributeMetadata, *pFeature); } } vector<LocationType> vertices; pCurrentObject->getRotatedExtents(vertices); for (vector<LocationType>::const_iterator iter = vertices.begin(); iter != vertices.end(); ++iter) { LocationType geo = pGeoref->convertPixelToGeocoord(*iter); pFeature->addVertex(geo.mY, geo.mX); } } } } else { // The BitMaskIterator does not support negative extents and // the BitMask does not correctly handle the outside flag so // the BitMaskIterator is used for cases when the outside flag is true and // the BitMask is used for cases when the outside flag is false AoiElement* pAoiElement = dynamic_cast<AoiElement*>(pGraphicElement); VERIFYRV(pAoiElement != NULL, features); const BitMask* pMask = pAoiElement->getSelectedPoints(); if (pObject != NULL) { pMask = pObject->getPixels(); if (pMask == NULL) { message = "The " + pObject->getName() + " object cannot be represented by the " + StringUtilities::toDisplayString(mShape) + " shape type, so a feature will not be added."; return features; } } if (pMask != NULL) { BitMaskIterator maskIt(pMask, pGeoref); if ((maskIt.getCount() > 0 && pMask->isOutsideSelected() == true) || (pMask->getCount() > 0 && pMask->isOutsideSelected() == false)) { // Add the feature SessionItem* pSessionItem = pGraphicElement; if (pObject != NULL) { pSessionItem = pObject; } Feature* pFeature = new Feature(pSessionItem); features.push_back(pFeature); mFeatures.push_back(pFeature); VERIFYNR(pFeature->attach(SIGNAL_NAME(Subject, Modified), Slot(this, &ShapeFile::shapeModified))); // Fields pFeature->addField("Name", string()); if (!elementName.empty()) { if (pObject != NULL) { pFeature->setFieldValue("Name", elementName + ": " + pObject->getName()); } else { pFeature->setFieldValue("Name", elementName); } } // Vertices int startColumn = 0; int endColumn = 0; int startRow = 0; int endRow = 0; if (pMask->isOutsideSelected() == true) { maskIt.getBoundingBox(startColumn, startRow, endColumn, endRow); } else { pMask->getBoundingBox(startColumn, startRow, endColumn, endRow); } LocationType pixel; for (int i = startColumn; i <= endColumn; i++) { for (int j = startRow; j <= endRow; j++) { if ((maskIt.getPixel(i, j) && pMask->isOutsideSelected() == true) || (pMask->getPixel(i, j) && pMask->isOutsideSelected() == false)) { pixel.mX = i + 0.5; pixel.mY = j + 0.5; pixel = pGeoref->convertPixelToGeocoord(pixel); pFeature->addVertex(pixel.mY, pixel.mX); // Longitude as x-coord } } } } } } } break; default: message = "Shape type not recognized."; return features; } if (features.empty()) { message = elementName + " has no objects that can be represented with the " + StringUtilities::toDisplayString(mShape) + " shape type, so no features can be added."; } return features; }
vector<Feature*> ShapeFile::addFeatures(DataElement* pElement, RasterElement* pGeoref, string& message) { vector<Feature*> features; message.clear(); if (pElement == NULL) { message = "Features cannot be added because the data element is invalid!"; return features; } if (pGeoref == NULL || !pGeoref->isGeoreferenced()) { message = "No georeferencing information can be found."; return features; } // Create the features string elementName = pElement->getName(); AoiElement* pAoi = dynamic_cast<AoiElement*>(pElement); if (pAoi != NULL) { if (mShape == POINT_SHAPE) { // The BitMaskIterator does not support negative extents and // the BitMask does not correctly handle the outside flag so // the BitMaskIterator is used for cases when the outside flag is true and // the BitMask is used for cases when the outside flag is false const BitMask* pMask = pAoi->getSelectedPoints(); if (pMask != NULL) { BitMaskIterator maskIt(pMask, pGeoref); if ((maskIt.getCount() > 0 && pMask->isOutsideSelected() == true) || (pMask->getCount() > 0 && pMask->isOutsideSelected() == false)) { // Add features for each selected pixel int startColumn = 0; int endColumn = 0; int startRow = 0; int endRow = 0; if (pMask->isOutsideSelected() == true) { maskIt.getBoundingBox(startColumn, startRow, endColumn, endRow); } else { pMask->getBoundingBox(startColumn, startRow, endColumn, endRow); } LocationType pixel; for (int i = startColumn; i <= endColumn; i++) { for (int j = startRow; j <= endRow; j++) { if ((maskIt.getPixel(i, j) && pMask->isOutsideSelected() == true) || (pMask->getPixel(i, j) && pMask->isOutsideSelected() == false)) { // Add the feature Feature* pFeature = new Feature(mShape); if (pFeature != NULL) { features.push_back(pFeature); mFeatures.push_back(pFeature); pFeature->attach(SIGNAL_NAME(Subject, Modified), Slot(this, &ShapeFile::shapeModified)); pixel.mX = i + 0.5; pixel.mY = j + 0.5; // Fields pFeature->addField("Name", string()); pFeature->addField("Pixel", string()); if (!elementName.empty()) { pFeature->setFieldValue("Name", elementName); } string pixelName = ""; if (!pixelName.empty()) { pFeature->setFieldValue("Pixel", pixelName); } // Vertex pixel = pGeoref->convertPixelToGeocoord(pixel); pFeature->addVertex(pixel.mY, pixel.mX); // Longitude as x-coord } } } } } } } else if (mShape == POLYLINE_SHAPE) { GraphicGroup* pGroup = pAoi->getGroup(); if (pGroup != NULL) { const list<GraphicObject*>& objects = pGroup->getObjects(); if (objects.empty()) { message = "Error Shape File 101: Cannot create a shape file from an empty AOI."; return features; } else if (objects.size() != 1) { message = "Error Shape File 102: Can only create a polyline shape file " "from an AOI which contains a single object."; return features; } const PolylineObject* pObj = dynamic_cast<const PolylineObject*>(objects.front()); if (pObj == NULL || pObj->getGraphicObjectType() != POLYLINE_OBJECT) { message = "Error Shape File 103: Can only create a polyline shape file " "from an AOI which contains a single polyline."; return features; } const std::vector<LocationType>& vertices = pObj->getVertices(); Feature* pFeature = new Feature(mShape); if (pFeature != NULL) { features.push_back(pFeature); mFeatures.push_back(pFeature); pFeature->attach(SIGNAL_NAME(Subject, Modified), Slot(this, &ShapeFile::shapeModified)); pFeature->addField("Name", string()); if (!elementName.empty()) { pFeature->setFieldValue("Name", elementName); } for (vector<LocationType>::const_iterator iter = vertices.begin(); iter != vertices.end(); ++iter) { LocationType geo = pGeoref->convertPixelToGeocoord(*iter); pFeature->addVertex(geo.mY, geo.mX); } } } } else if (mShape == POLYGON_SHAPE) { GraphicGroup* pGroup = pAoi->getGroup(); if (pGroup != NULL) { const list<GraphicObject*>& objects = pGroup->getObjects(); if (objects.empty()) { message = "Error Shape File 101: Cannot create a shape file from an empty AOI."; return features; } else if (objects.size() != 1) { message = "Error Shape File 102: Can only create a polygon shape file " "from an AOI which contains a single object."; return features; } const PolygonObject* pObj = dynamic_cast<const PolygonObject*>(objects.front()); if (pObj == NULL || pObj->getGraphicObjectType() != POLYGON_OBJECT) { message = "Error Shape File 103: Can only create a polygon shape file " "from an AOI which contains a single polygon."; return features; } const std::vector<LocationType>& vertices = pObj->getVertices(); Feature* pFeature = new Feature(mShape); if (pFeature != NULL) { features.push_back(pFeature); mFeatures.push_back(pFeature); pFeature->attach(SIGNAL_NAME(Subject, Modified), Slot(this, &ShapeFile::shapeModified)); pFeature->addField("Name", string()); if (!elementName.empty()) { pFeature->setFieldValue("Name", elementName); } for (vector<LocationType>::const_iterator iter = vertices.begin(); iter != vertices.end(); ++iter) { LocationType geo = pGeoref->convertPixelToGeocoord(*iter); pFeature->addVertex(geo.mY, geo.mX); } } } } else if (mShape == MULTIPOINT_SHAPE) { // The BitMaskIterator does not support negative extents and // the BitMask does not correctly handle the outside flag so // the BitMaskIterator is used for cases when the outside flag is true and // the BitMask is used for cases when the outside flag is false const BitMask* pMask = pAoi->getSelectedPoints(); if (pMask != NULL) { BitMaskIterator maskIt(pMask, pGeoref); if ((maskIt.getCount() > 0 && pMask->isOutsideSelected() == true) || (pMask->getCount() > 0 && pMask->isOutsideSelected() == false)) { // Add the feature Feature* pFeature = new Feature(mShape); if (pFeature != NULL) { features.push_back(pFeature); mFeatures.push_back(pFeature); pFeature->attach(SIGNAL_NAME(Subject, Modified), Slot(this, &ShapeFile::shapeModified)); // Fields pFeature->addField("Name", string()); if (!elementName.empty()) { pFeature->setFieldValue("Name", elementName); } // Vertices int startColumn = 0; int endColumn = 0; int startRow = 0; int endRow = 0; if (pMask->isOutsideSelected() == true) { maskIt.getBoundingBox(startColumn, startRow, endColumn, endRow); } else { pMask->getBoundingBox(startColumn, startRow, endColumn, endRow); } LocationType pixel; for (int i = startColumn; i <= endColumn; i++) { for (int j = startRow; j <= endRow; j++) { if ((maskIt.getPixel(i, j) && pMask->isOutsideSelected() == true) || (pMask->getPixel(i, j) && pMask->isOutsideSelected() == false)) { pixel.mX = i + 0.5; pixel.mY = j + 0.5; pixel = pGeoref->convertPixelToGeocoord(pixel); pFeature->addVertex(pixel.mY, pixel.mX); // Longitude as x-coord } } } } } } } else { message = "Shape type not recognized."; return features; } } if (features.empty()) { message = elementName + " has no selected points, so no features can be added."; } return features; }