Skip to content

Commit

Permalink
support writing GeoJSON as a 'format' of the text writer
Browse files Browse the repository at this point in the history
  • Loading branch information
hobu committed Oct 22, 2012
1 parent e2f8c6e commit 406705f
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 33 deletions.
7 changes: 2 additions & 5 deletions include/pdal/drivers/text/Writer.hpp
Expand Up @@ -87,10 +87,6 @@ class PDAL_DLL Writer : public pdal::Writer
virtual void initialize();
virtual const Options getDefaultOptions() const;

// for dumping
virtual boost::property_tree::ptree toPTree() const;


protected:
virtual void writeBegin(boost::uint64_t targetNumPointsToWrite);
virtual boost::uint32_t writeBuffer(const PointBuffer&);
Expand All @@ -108,7 +104,8 @@ class PDAL_DLL Writer : public pdal::Writer
void WriteHeader(pdal::Schema const& schema);
std::vector<boost::tuple<std::string, std::string> > getDimensionOrder(pdal::Schema const& schema) const;
FileStreamPtr m_stream;
bool m_wrote_header;
bool bWroteHeader;
bool bWroteFirstPoint;
};

}
Expand Down
143 changes: 115 additions & 28 deletions src/drivers/text/Writer.cpp
Expand Up @@ -81,7 +81,8 @@ struct FileStreamDeleter

Writer::Writer(Stage& prevStage, const Options& options)
: pdal::Writer(prevStage, options)
, m_wrote_header(false)
, bWroteHeader(false)
, bWroteFirstPoint(false)

{

Expand Down Expand Up @@ -137,9 +138,22 @@ void Writer::writeBegin(boost::uint64_t /*targetNumPointsToWrite*/)

void Writer::writeEnd(boost::uint64_t /*actualNumPointsWritten*/)
{
std::string outputType = getOptions().getValueOrDefault<std::string>("format", "csv");
bool bGeoJSON = boost::iequals(outputType, "GEOJSON");
{
*m_stream << "]}";
std::string callback = getOptions().getValueOrDefault<std::string>("jscallback", "");

if (callback.size())
{
*m_stream <<")";
}
}

m_stream.reset();
m_stream = FileStreamPtr();
m_wrote_header = false;
bWroteHeader = false;
bWroteFirstPoint = false;
return;
}

Expand Down Expand Up @@ -237,7 +251,7 @@ void Writer::WriteHeader(pdal::Schema const& schema)
if (!bWriteHeader)
{
log()->get(logDEBUG) << "Not writing header" << std::endl;
m_wrote_header = true;
bWroteHeader = true;
return;

}
Expand Down Expand Up @@ -275,6 +289,23 @@ void Writer::WriteHeader(pdal::Schema const& schema)
}
log()->get(logDEBUG) << oss.str() << std::endl;

// If we're bGeoJSON, we're just going to write the preamble for FeatureCollection,
// and let the rest happen in writeBuffer
std::string outputType = getOptions().getValueOrDefault<std::string>("format", "csv");
bool bGeoJSON = boost::iequals(outputType, "GEOJSON");
if (bGeoJSON)
{
std::string callback = getOptions().getValueOrDefault<std::string>("jscallback", "");

if (callback.size())
{
*m_stream << callback <<"(";
}
*m_stream << "{ \"type\": \"FeatureCollection\", \"features\": [";
return;
}


if (delimiter.size() == 0)
delimiter = " ";

Expand Down Expand Up @@ -405,10 +436,14 @@ std::string Writer::getStringRepresentation(PointBuffer const& data,
boost::uint32_t Writer::writeBuffer(const PointBuffer& data)
{

if (!m_wrote_header)
std::string outputType = getOptions().getValueOrDefault<std::string>("format", "csv");
bool bCSV = boost::iequals(outputType, "CSV");
bool bGeoJSON = boost::iequals(outputType, "GEOJSON");

if (!bWroteHeader)
{
WriteHeader(data.getSchema());
m_wrote_header = true;
bWroteHeader = true;
}

std::string newline = getOptions().getValueOrDefault<std::string>("newline", "\n");
Expand All @@ -425,45 +460,97 @@ boost::uint32_t Writer::writeBuffer(const PointBuffer& data)

std::vector<boost::tuple<std::string, std::string> > dimensions = getDimensionOrder(schema);

while (pointIndex != data.getNumPoints())

if (bCSV)
{
std::vector<boost::tuple<std::string, std::string> >::const_iterator iter = dimensions.begin();

while (iter != dimensions.end())
while (pointIndex != data.getNumPoints())
{

Dimension const& d = schema.getDimension(iter->get<0>(), iter->get<1>());
if (d.isIgnored())
std::vector<boost::tuple<std::string, std::string> >::const_iterator iter = dimensions.begin();

while (iter != dimensions.end())
{

Dimension const& d = schema.getDimension(iter->get<0>(), iter->get<1>());
if (d.isIgnored())
{
iter++;
continue;
}

*m_stream << getStringRepresentation(data, d, pointIndex);

iter++;
continue;
if (iter != dimensions.end())
*m_stream << delimiter;
}
*m_stream << newline;

*m_stream << getStringRepresentation(data, d, pointIndex);
pointIndex++;
if (!bWroteFirstPoint)
{
bWroteFirstPoint = true;
}

iter++;
if (iter != dimensions.end())
*m_stream << delimiter;
}
*m_stream << newline;
}
} else if (bGeoJSON)
{
while (pointIndex != data.getNumPoints())
{
Dimension const& dimX = schema.getDimension("X");
Dimension const& dimY = schema.getDimension("Y");
Dimension const& dimZ = schema.getDimension("Z");

if (bWroteFirstPoint)
*m_stream << ",";

*m_stream << "{ \"type\":\"Feature\",\"geometry\": { \"type\": \"Point\", \"coordinates\": [";
*m_stream << getStringRepresentation(data, dimX, pointIndex) << ",";
*m_stream << getStringRepresentation(data, dimY, pointIndex) << ",";
*m_stream << getStringRepresentation(data, dimZ, pointIndex) << "]},";

*m_stream << "\"properties\": {";

pointIndex++;
std::vector<boost::tuple<std::string, std::string> >::const_iterator iter = dimensions.begin();

}
while (iter != dimensions.end())
{

Dimension const& d = schema.getDimension(iter->get<0>(), iter->get<1>());
if (d.isIgnored())
{
iter++;
continue;
}

*m_stream << "\"" << iter->get<0>() << "\":";


return data.getNumPoints();
}
*m_stream << "\"" << getStringRepresentation(data, d, pointIndex) <<"\"";

iter++;
if (iter != dimensions.end())
*m_stream << delimiter;
}


*m_stream << "}"; // end properties

*m_stream << "}"; // end feature

pointIndex++;
if (!bWroteFirstPoint)
{
bWroteFirstPoint = true;
}


}

}

boost::property_tree::ptree Writer::toPTree() const
{
boost::property_tree::ptree tree = pdal::Writer::toPTree();

// add stuff here specific to this stage type

return tree;
return data.getNumPoints();
}


Expand Down
28 changes: 28 additions & 0 deletions test/data/pipeline/pipeline_geojson.xml
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<Pipeline version="1.0">
<Writer type="drivers.text.writer">
<Option name="filename">
../../temp/autzen-point-format-3.txt
</Option>
<Option name="order">
Red,Green,X,Y,Blue,Z
</Option>
<Option name="keep_unspecified">
true
</Option>
<Option name="format">
geojson
</Option>
<Option name="chunk_size">
10
</Option>
<Option name="jscallback">
pointcloud_callback
</Option>
<Reader type="drivers.las.reader">
<Option name="filename">
../autzen-point-format-3.las
</Option>
</Reader>
</Writer>
</Pipeline>

0 comments on commit 406705f

Please sign in to comment.