Skip to content
Snippets Groups Projects
Commit 7c58a968 authored by Emmanuel Christophe's avatar Emmanuel Christophe
Browse files

ENH: KMLVectorDataIO optimization

parent 330881f0
No related branches found
No related tags found
No related merge requests found
......@@ -64,6 +64,8 @@ public:
/** Data typedef */
typedef TData VectorDataType;
typedef typename VectorDataType::DataTreeType DataTreeType;
typedef typename DataTreeType::TreeNodeType InternalTreeNodeType;
typedef typename InternalTreeNodeType::ChildrenListType ChildrenListType;
typedef typename DataTreeType::Pointer DataTreePointerType;
typedef typename DataTreeType::ConstPointer DataTreeConstPointerType;
typedef typename VectorDataType::DataNodeType DataNodeType;
......@@ -147,12 +149,22 @@ protected:
DataNodePointerType ConvertGeometryToPolygonNode(const GeometryPtr& geometry);
/** end conversion tools */
typedef kmldom::KmlPtr KmlPtr;
typedef kmldom::KmlFactory KmlFactory;
typedef kmldom::DocumentPtr DocumentPtr;
typedef kmldom::FolderPtr FolderPtr;
typedef kmldom::MultiGeometryPtr MultiGeometryPtr;
void ProcessNodeWrite(InternalTreeNodeType * source, KmlFactory* factory,
KmlPtr kml, DocumentPtr currentDocument, FolderPtr currentFolder,
MultiGeometryPtr currentMultiGeometry);
private:
KMLVectorDataIO(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
DataTreePointerType m_Tree;
unsigned int m_Kept;
};
} // end namespace otb
......
......@@ -36,6 +36,8 @@ PURPOSE. See the above copyright notices for more information.
#include "ossimOgcWktTranslator.h"
#include "otbMetaDataKey.h"
#include "itkTimeProbe.h"
#include "ogrsf_frmts.h"
using kmldom::ElementPtr;
......@@ -546,7 +548,8 @@ bool KMLVectorDataIO<TData>::CanWriteFile( const char* filename )
template<class TData>
void KMLVectorDataIO<TData>::Write(const VectorDataConstPointerType data)
{
itk::TimeProbe chrono;
chrono.Start();
// Retrieve data required for georeferencing
std::string projectionRefWkt = data->GetProjectionRef();
......@@ -560,6 +563,8 @@ void KMLVectorDataIO<TData>::Write(const VectorDataConstPointerType data)
}
delete oSRS;
m_Kept = 0;
//Create the factory
KmlFactory* factory = KmlFactory::GetFactory();
if (factory == NULL)
......@@ -581,151 +586,198 @@ void KMLVectorDataIO<TData>::Write(const VectorDataConstPointerType data)
DocumentPtr currentDocument = NULL;
FolderPtr currentFolder = NULL;
MultiGeometryPtr currentMultiGeometry = NULL;
PolygonPtr currentPolygon = NULL;
OuterBoundaryIsPtr outerboundaryis = NULL;
InnerBoundaryIsPtr innerboundaryis = NULL;
// Note that we force a precise structure when we write a kml file.
InternalTreeNodeType * inputRoot = const_cast<InternalTreeNodeType *>(tree->GetRoot());
ProcessNodeWrite(inputRoot, factory, kml, currentDocument, currentFolder, currentMultiGeometry);
// Serialize to XML
std::string xml = kmldom::SerializePretty(kml);
// Write it
kmlbase::File::WriteStringToFile(xml,this->m_FileName);
// Eventually print it
//std::cout << xml;
chrono.Stop();
std::cout<<"KMLVectorDataIO: file saved in "<<chrono.GetMeanTime()<<" seconds. (" << m_Kept << " elements)"<<std::endl;
otbMsgDevMacro( <<" KMLVectorDataIO::Write() ");
}
template<class TData>
void KMLVectorDataIO<TData>::ProcessNodeWrite(InternalTreeNodeType * source, KmlFactory* factory, KmlPtr kml, DocumentPtr currentDocument, FolderPtr currentFolder, MultiGeometryPtr currentMultiGeometry)
{
// Note that we force a precise structure when we write a kml file.
// We will necessary have a <document> that will contain a <folder>.
// And in a folder there automatically will be one or several <placemark>.
while (!it.IsAtEnd())
// Get the children list from the input node
ChildrenListType children = source->GetChildrenList();
// std::cout << "Found " << children.size() << " children" << std::endl;
// For each child
for(typename ChildrenListType::iterator it = children.begin(); it!=children.end(); ++it)
{
switch (it.Get()->GetNodeType())
{
case ROOT:
{
break;
}
case DOCUMENT:
DataNodePointerType dataNode = (*it)->Get();
// std::cout << "Processing " << dataNode->GetNodeType() << " with Id: " << dataNode->GetNodeId() << std::endl;
++m_Kept;
switch (dataNode->GetNodeType())
{
DocumentPtr document = factory->CreateDocument();
if (it.Get()->HasField("name"))
case ROOT:
{
std::string fieldname = it.Get()->GetField("name");
document->set_name(fieldname);
break;
}
kml->set_feature(document);
currentDocument = document;
break;
}
case FOLDER:
{
FolderPtr folder = factory->CreateFolder();
std::string fieldname = it.Get()->GetField("name");
folder->set_name(fieldname);
currentDocument->add_feature(folder);
currentFolder = folder;
break;
}
case FEATURE_POINT:
{
// Create <coordinates>
CoordinatesPtr coordinates = factory->CreateCoordinates();
PointType pointCoord = it.Get()->GetPoint();
if (DataNodeType::Dimension>2)
case DOCUMENT:
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],pointCoord[2]);
DocumentPtr document = factory->CreateDocument();
if (dataNode->HasField("name"))
{
std::string fieldname = dataNode->GetField("name");
document->set_name(fieldname);
}
kml->set_feature(document);
currentDocument = document;
ProcessNodeWrite(*it, factory, kml, currentDocument, currentFolder, currentMultiGeometry);
break;
}
else
case FOLDER:
{
coordinates->add_latlng(pointCoord[1],pointCoord[0]);
FolderPtr folder = factory->CreateFolder();
std::string fieldname = dataNode->GetField("name");
folder->set_name(fieldname);
currentDocument->add_feature(folder);
currentFolder = folder;
ProcessNodeWrite(*it, factory, kml, currentDocument, currentFolder, currentMultiGeometry);
break;
}
case FEATURE_POINT:
{
// Create <coordinates>
CoordinatesPtr coordinates = factory->CreateCoordinates();
PointType pointCoord = dataNode->GetPoint();
if (DataNodeType::Dimension>2)
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],pointCoord[2]);
}
else
{
coordinates->add_latlng(pointCoord[1],pointCoord[0]);
}
// Create <Point> and give it <coordinates>.
PointPtr point = factory->CreatePoint();
point->set_coordinates(coordinates);
if (currentMultiGeometry != NULL)
{
currentMultiGeometry->add_geometry(point);
}
else
{
PointPtr point = factory->CreatePoint();
point->set_coordinates(coordinates);
PlacemarkPtr placemark = factory->CreatePlacemark();
placemark->set_geometry(point);
if (currentFolder!= NULL)
if (currentMultiGeometry != NULL)
{
currentFolder->add_feature(placemark);
currentMultiGeometry->add_geometry(point);
}
else
{
currentDocument->add_feature(placemark);
}
PlacemarkPtr placemark = factory->CreatePlacemark();
placemark->set_geometry(point);
if (currentFolder!= NULL)
{
currentFolder->add_feature(placemark);
}
else
{
currentDocument->add_feature(placemark);
}
}
break;
}
break;
}
case FEATURE_LINE:
{
case FEATURE_LINE:
{
VertexListConstPointerType vertexList = it.Get()->GetLine()->GetVertexList();
VertexListConstPointerType vertexList = dataNode->GetLine()->GetVertexList();
// Create <coordinates>
CoordinatesPtr coordinates = factory->CreateCoordinates();
LineStringPtr line = factory->CreateLineString();
CoordinatesPtr coordinates = factory->CreateCoordinates();
LineStringPtr line = factory->CreateLineString();
typename VertexListType::ConstIterator vIt = vertexList->Begin();
typename VertexListType::ConstIterator vIt = vertexList->Begin();
while (vIt != vertexList->End())
{
VertexType pointCoord = vIt.Value();
if (DataNodeType::Dimension>2)
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],pointCoord[2]);
}
else
while (vIt != vertexList->End())
{
coordinates->add_latlng(pointCoord[1],pointCoord[0]);
VertexType pointCoord = vIt.Value();
if (DataNodeType::Dimension>2)
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],pointCoord[2]);
}
else
{
coordinates->add_latlng(pointCoord[1],pointCoord[0]);
}
line->set_coordinates(coordinates);
++vIt;
}
line->set_coordinates(coordinates);
++vIt;
}
if (currentMultiGeometry != NULL)
{
currentMultiGeometry->add_geometry(line);
}
else
{
PlacemarkPtr placemark = factory->CreatePlacemark();
placemark->set_geometry(line);
if (currentFolder!= NULL)
if (currentMultiGeometry != NULL)
{
currentFolder->add_feature(placemark);
currentMultiGeometry->add_geometry(line);
}
else
{
currentDocument->add_feature(placemark);
PlacemarkPtr placemark = factory->CreatePlacemark();
placemark->set_geometry(line);
if (currentFolder!= NULL)
{
currentFolder->add_feature(placemark);
}
else
{
currentDocument->add_feature(placemark);
}
}
break;
}
break;
}
case FEATURE_POLYGON:
{//TODO refine the solution of drawing the polygon 1m above the ground
case FEATURE_POLYGON:
{//TODO refine the solution of drawing the polygon 1m above the ground
// In a polygon we just can find any LinearRings
LinearRingPtr line = factory->CreateLinearRing();
PolygonPtr polygon = factory->CreatePolygon();
polygon->set_extrude(true);
polygon->set_altitudemode(1);//ALTITUDEMODE_RELATIVETOGROUND
LinearRingPtr line = factory->CreateLinearRing();
PolygonPtr polygon = factory->CreatePolygon();
CoordinatesPtr coordinates = factory->CreateCoordinates();
OuterBoundaryIsPtr outerboundaryis = factory->CreateOuterBoundaryIs();
InnerBoundaryIsPtr innerboundaryis = factory->CreateInnerBoundaryIs();
polygon->set_extrude(true);
polygon->set_altitudemode(1);//ALTITUDEMODE_RELATIVETOGROUND
VertexListConstPointerType vertexList = it.Get()->GetPolygonExteriorRing()->GetVertexList();
CoordinatesPtr coordinates = factory->CreateCoordinates();
OuterBoundaryIsPtr outerboundaryis = factory->CreateOuterBoundaryIs();
InnerBoundaryIsPtr innerboundaryis = factory->CreateInnerBoundaryIs();
typename VertexListType::ConstIterator vIt = vertexList->Begin();
VertexListConstPointerType vertexList = dataNode->GetPolygonExteriorRing()->GetVertexList();
if (vIt == vertexList->End())
{
itkExceptionMacro(<<"Polygon is empty");
}
typename VertexListType::ConstIterator vIt = vertexList->Begin();
while (vIt != vertexList->End())
{
if (vIt == vertexList->End())
{
itkExceptionMacro(<<"Polygon is empty");
}
while (vIt != vertexList->End())
{
VertexType pointCoord = vIt.Value();
if (DataNodeType::Dimension>2)
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],pointCoord[2]+1);//Drawing polygon 1m above ground to avoid z-buffer issues
}
else
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],1);//Drawing polygon 1m above ground to avoid z-buffer issues
}
line->set_coordinates(coordinates);
++vIt;
}
//Adding the first point again to close the polygon
vIt = vertexList->Begin();
VertexType pointCoord = vIt.Value();
if (DataNodeType::Dimension>2)
{
......@@ -735,37 +787,37 @@ void KMLVectorDataIO<TData>::Write(const VectorDataConstPointerType data)
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],1);//Drawing polygon 1m above ground to avoid z-buffer issues
}
line->set_coordinates(coordinates);
++vIt;
}
//Adding the first point again to close the polygon
vIt = vertexList->Begin();
VertexType pointCoord = vIt.Value();
if (DataNodeType::Dimension>2)
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],pointCoord[2]+1);//Drawing polygon 1m above ground to avoid z-buffer issues
}
else
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],1);//Drawing polygon 1m above ground to avoid z-buffer issues
}
line->set_coordinates(coordinates);
outerboundaryis->set_linearring(line);
polygon->set_outerboundaryis(outerboundaryis);
outerboundaryis->set_linearring(line);
polygon->set_outerboundaryis(outerboundaryis);
// Retrieving internal rings as well
for (typename PolygonListType::Iterator pIt = it.Get()->GetPolygonInteriorRings()->Begin();
pIt!=it.Get()->GetPolygonInteriorRings()->End();++pIt)
{
for (typename PolygonListType::Iterator pIt = dataNode->GetPolygonInteriorRings()->Begin();
pIt!=dataNode->GetPolygonInteriorRings()->End();++pIt)
{
vertexList = pIt.Get()->GetVertexList();
vIt = vertexList->Begin();
vertexList = pIt.Get()->GetVertexList();
vIt = vertexList->Begin();
while (vIt != vertexList->End())
{
while (vIt != vertexList->End())
{
vIt = vertexList->Begin();
VertexType pointCoord = vIt.Value();
if (DataNodeType::Dimension>2)
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],pointCoord[2]+1);//Drawing polygon 1m above ground to avoid z-buffer issues
}
else
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],1);//Drawing polygon 1m above ground to avoid z-buffer issues
}
line->set_coordinates(coordinates);
++vIt;
}
//Adding the first point again to close the polygon
vIt = vertexList->Begin();
VertexType pointCoord = vIt.Value();
if (DataNodeType::Dimension>2)
......@@ -779,38 +831,40 @@ void KMLVectorDataIO<TData>::Write(const VectorDataConstPointerType data)
line->set_coordinates(coordinates);
++vIt;
innerboundaryis->set_linearring(line);
polygon->add_innerboundaryis(innerboundaryis);
innerboundaryis->clear_linearring();
}
//Adding the first point again to close the polygon
vIt = vertexList->Begin();
VertexType pointCoord = vIt.Value();
if (DataNodeType::Dimension>2)
if (currentMultiGeometry != NULL)
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],pointCoord[2]+1);//Drawing polygon 1m above ground to avoid z-buffer issues
currentMultiGeometry->add_geometry(polygon);
}
else
{
coordinates->add_latlngalt(pointCoord[1],pointCoord[0],1);//Drawing polygon 1m above ground to avoid z-buffer issues
PlacemarkPtr placemark = factory->CreatePlacemark();
placemark->set_geometry(polygon);
if (currentFolder!= NULL)
{
currentFolder->add_feature(placemark);
}
else
{
currentDocument->add_feature(placemark);
}
}
line->set_coordinates(coordinates);
++vIt;
innerboundaryis->set_linearring(line);
polygon->add_innerboundaryis(innerboundaryis);
innerboundaryis->clear_linearring();
break;
}
if (currentMultiGeometry != NULL)
{
currentMultiGeometry->add_geometry(polygon);
}
else
// MultiGeometry
case FEATURE_COLLECTION:
{
MultiGeometryPtr multi = factory->CreateMultiGeometry();
currentMultiGeometry = multi;
PlacemarkPtr placemark = factory->CreatePlacemark();
placemark->set_geometry(polygon);
placemark->set_geometry(multi);
if (currentFolder!= NULL)
{
currentFolder->add_feature(placemark);
......@@ -819,46 +873,18 @@ void KMLVectorDataIO<TData>::Write(const VectorDataConstPointerType data)
{
currentDocument->add_feature(placemark);
}
ProcessNodeWrite(*it, factory, kml, currentDocument, currentFolder, currentMultiGeometry);
break;
}
break;
}
// MultiGeometry
case FEATURE_COLLECTION:
{
MultiGeometryPtr multi = factory->CreateMultiGeometry();
currentMultiGeometry = multi;
PlacemarkPtr placemark = factory->CreatePlacemark();
placemark->set_geometry(multi);
if (currentFolder!= NULL)
{
currentFolder->add_feature(placemark);
}
else
{
currentDocument->add_feature(placemark);
}
break;
}
default :
break;
default :
break;
} // end switch
++it;
} // end while
// Serialize to XML
std::string xml = kmldom::SerializePretty(kml);
// Write it
kmlbase::File::WriteStringToFile(xml,this->m_FileName);
// Eventually print it
//std::cout << xml;
otbMsgDevMacro( <<" KMLVectorDataIO::Write() ");
} // end for
}
} // end namespace otb
#endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment