I'm parsing the mayotte pbf with osmium, and my handler is looking for ways. When I find one I process its barycentre and print it. The issue I ran into is that all of the ways I process have invalid location. And if print the location I get undefined for both latitude and longitude.
Is there an issue with my PBF file, or with my understanding of the osmium library?
Here is a mcve:
/**
* To compile this script, you should first install `libosmium` and its
* dependencies. Then:
* g++ -std=c++11 -lz -lexpat -lbz2 mcve.cpp -o mcve
*/
#include <iostream>
#include <osmium/handler.hpp>
#include <osmium/io/any_input.hpp>
#include <osmium/osm/node.hpp>
#include <osmium/osm/way.hpp>
#include <osmium/visitor.hpp>
class ParkingAndCarpoolingAreasHandler : public osmium::handler::Handler {
public:
void way(const osmium::Way& way) {
double lng;
double lat;
double count = 0.0;
for (const osmium::NodeRef& nr : way.nodes()) {
if (!nr.location().valid()) {
std::cerr << "Way (id=" << way.id()
<< " version=" << way.version()
<< " timestamp=" << way.timestamp()
<< " visible=" << (way.visible() ? "true" : "false")
<< " changeset=" << way.changeset()
<< " uid=" << way.uid()
<< " user=" << way.user() << ")\n";
std::cerr << "NodeRef (ref=" << nr.ref() << " location=" << nr.location() << ")\n";
std::cerr << std::endl;
return;
}
count++;
lng += nr.location().lon();
lat += nr.location().lat();
}
lng /= count;
lat /= count;
std::cout << "POINT(" << lat << ' ' << lng << ")\n";
}
};
int main() {
auto otypes = osmium::osm_entity_bits::node | osmium::osm_entity_bits::way;
osmium::io::Reader reader{"tmp/mayotte-latest.osm.pbf", otypes};
ParkingAndCarpoolingAreasHandler handler;
osmium::apply(reader, handler);
reader.close();
}
In OSM a way typically stores only references to the node it consists of. These references just contain the node ID but no additional information (such as coordinates and tags). To obtain node coordinates you have to look at the actual nodes, not just at their reference.
See OSM XML and PBF Format for more information.
Since I have no experience with osmium I can't tell you how to retrieve the corresponding nodes by their IDs. However according to the Osmium Concepts Manual you can use a NodeLocationsForWays handler to populate your NodeRef objects with locations. examples/osmium_road_length.cpp contains an example.
Related
I am a newbie in pugixml. Consider I have XML given here. I want to get value of Name and Roll of Every Student. The code below only find the tag but not the value.
#include <iostream>
#include "pugixml.hpp"
int main()
{
std::string xml_mesg = "<data> \
<student>\
<Name>student 1</Name>\
<Roll>111</Roll>\
</student>\
<student>\
<Name>student 2</Name>\
<Roll>222</Roll>\
</student>\
<student>\
<Name>student 3</Name>\
<Roll>333</Roll>\
</student>\
</data>";
pugi::xml_document doc;
doc.load_string(xml_mesg.c_str());
pugi::xml_node data = doc.child("data");
for(pugi::xml_node_iterator it=data.begin(); it!=data.end(); ++it)
{
for(pugi::xml_node_iterator itt=it->begin(); itt!=it->end(); ++itt)
std::cout << itt->name() << " " << std::endl;
}
return 0;
}
I want the output of Name and Roll for each student. How can I modify above code? Also, if one can refer here(press Test), I can directly write xpath which is supported by pugixml. If so, how can I get the values I seek using Xpath in Pugixml.
Here's how you can do it with just Xpath:
pugi::xpath_query student_query("/data/student");
pugi::xpath_query name_query("Name/text()");
pugi::xpath_query roll_query("Roll/text()");
pugi::xpath_node_set xpath_students = doc.select_nodes(student_query);
for (pugi::xpath_node xpath_student : xpath_students)
{
// Since Xpath results can be nodes or attributes, you must explicitly get
// the node out with .node()
pugi::xml_node student = xpath_student.node();
pugi::xml_node name = student.select_node(name_query).node();
pugi::xml_node roll = student.select_node(roll_query).node();
std::cout << "Student name: " << name.value() << std::endl;
std::cout << " roll: " << roll.value() << std::endl;
}
I think that the reason why you are getting the "tags/nodes" instead of their values is because you are using the name() function instead of value(). Try replacing your itt->name() with itt->value() instead.
I found some good documentation about accessing document data here
Thanks #Cornstalks for the insight of using xpath in pugixml. I used child_value given here. The code of mine was thus:
for(pugi::xml_node_iterator it=data.begin(); it!=data.end(); ++it)
{
for(pugi::xml_node_iterator itt=it->begin(); itt!=it->end(); ++itt)
std::cout << itt->name() << " " << itt->child_value() << " " << std::endl;
}
I could also use xpath as #Cornstalks suggested thus making my code as:
pugi::xml_document doc;
doc.load_string(xml_mesg.c_str());
pugi::xpath_query student_query("/data/student");
pugi::xpath_query name_query("Name/text()");
pugi::xpath_query roll_query("Roll/text()");
pugi::xpath_node_set xpath_students = doc.select_nodes(student_query);
for (pugi::xpath_node xpath_student : xpath_students)
{
// Since Xpath results can be nodes or attributes, you must explicitly get
// the node out with .node()
pugi::xml_node student = xpath_student.node();
pugi::xml_node name = student.select_node(name_query).node();
pugi::xml_node roll = student.select_node(roll_query).node();
std::cout << "Student name: " << name.value() << std::endl;
std::cout << " roll: " << roll.value() << std::endl;
}
In your inner loop change the following line to get the values like :
student1 and 111 and so on...
std::cout << itt.text().get() << " " << std::endl;
I'm trying to use boost json with property trees to decode a json message. I'm only interested about checking whether "mykey" is in the message and, if that is the case, get the corresponding values.
I'm a little lost in boost documentation, and I was trying to see what the actual code would be to parse a message such as the one below.
{
// some values
"mykey": [
{
"var1": "value1_str",
"var2" : "value2"
}
]
// some other values
}
I don't know about Boost ptree for JSON. I've tried it but it seemed... very clunky.
Here's a simple JSON parser based on the RFC, made in Spirit: https://github.com/sehe/spirit-v2-json/tree/q21356666
You could use it for your use case like test.cpp
#include <vector>
#include "json.hpp"
struct X {
static X from_json(JSON::Value const& v);
std::string var1;
double var2;
};
int main()
{
auto doc = as_object(JSON::parse(
"{\n"
" // some values\n"
" \"mykey\": [\n"
" {\n"
" \"var1\": \"value1_str\",\n"
" \"var2\" : 3.14\n"
" }\n"
" ]\n"
" // some other values\n"
"}\n"
));
if (doc.has_key("mykey"))
{
X data = X::from_json(doc["mykey"]);
std::cout << "X.var1: " << data.var1 << "\n";
std::cout << "X.var2: " << data.var2 << "\n";
}
std::cout << "doc: " << doc << "\n";
std::cout << "doc[\"mykey\"]: " << doc["mykey"] << "\n";
}
X X::from_json(JSON::Value const& v)
{
X result;
auto& o = as_object(as_array(v)[0]);
result.var1 = as_string(o["var1"]);
result.var2 = as_double(o["var2"]);
return result;
}
Output:
X.var1: value1_str
X.var2: 3.14
doc: {"mykey":[{"var1":"value1_str","var2":3.14}]}
doc["mykey"]: [{"var1":"value1_str","var2":3.14}]
There are other json libraries around. I suggest you select one to suit your needs.
I'm looking for a very specific piece of information. I could make this a rather detailed question I guess but I'd rather try keeping it short and to the point.
I need to acces a piece of meta data (exif information) from within a Photoshop filter plug-in. I have never dealt with exif data from within a Photoshop plug-in or without and the PS SDK documentation is of a form that leaves a lot of questions. I would eventually get there but was wondering if anyone here has done this before and could help me out with an example. I'd be very grateful for that...
What we need should be documented here in the SDK:
documentation/html/group___resource_suite.html
documentation/html/imageresourcessection.html
The latter document says that the resource ID I need to retrieve the exif data is 1059 (decimal) and that accessing Exif data is supported since PS 7.0 which is good. But the SDK has no information (that I found) as to what you get, pointer? pointer to what? They just tell you to look at the exif spec. So do I get a pointer to the RAW binary exif data and if so how to I extract a field from that.
The specifications for the Exif data are here:
http://exif.org/specifications.html
As an example I'd like to get at this exif field:
Tag Name Field Name Dec Hex Type Count
Image title ImageDescription 270 10E ASCII Any
EDIT: After a deeper research I've found the following (an excerpt from the documentation):
Document: Photoshop API Guide.
Argument: Callbacks.
The callback routines are organized into “suites” collections of
related routines which implement a particular functionality.
The suites are described by a pointer to a record containing:
a 2 byte version number for the suite,
a 2 byte count of the number of routines in the suite,
a series of function pointers for the callback routines.
You are interested in the Property suite.
Current version: 1; Adobe Photoshop: 5.0; Routines: 2.
Properties are identified by a signature and key, which form a pair to
identify the property of interest.
Adobe Photoshop’s signature is always '8BIM' (0x3842494D).
The EXIF property is controlled by The Japan Electronic Industry Development Association (JEIDA) and Electronic Industries Association of Japan (EIAJ) which merged in Novemeber of 2000. The EXIF specification can be downloaded from their web site at the following location.
http://it.jeita.or.jp/jhistory/document/standard/exif_eng/jeida49eng.htm
GetPropertyProc( )
MACPASCAL OSErr (*GetPropertyProc) (OSType signature, OSType key, int32 index, int32 * simpleProperty, Handle * complexProperty);
This routine allows you to get information about the document currently being processed.
property name: propEXIFData
id:EXIF
type:complex (modifiable)
description:Camera and device data.
To recap I'll write some juicy code:
GetPropertyProc getProperty = formatParamBlock->propertyProcs->getPropertyProc;
rc = getProperty(0x3842494D, propEXIFData, 0, &simpProp, &compProp);
if ( rc )
return;
GetPIHandleSizeProc getSize = formatParamBlock->handleProcs->getSizeProc;
int32 size = getSize(compProp);
if ( !size )
return;
LockPIHandleProc lock = formatParamBlock->handleProcs->lockProc;
uint8* exif = (uint8 *)lock(compProp, false);
if ( !exif )
return;
Here's is a code sample using the Exiv2 Library: http://www.exiv2.org/doc/exifprint_8cpp-example.html
// ***************************************************************** -*- C++ -*-
// exifprint.cpp, $Rev: 2286 $
// Sample program to print the Exif metadata of an image
#include <exiv2/exiv2.hpp>
#include <iostream>
#include <iomanip>
#include <cassert>
int main(int argc, char* const argv[])
try {
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " file\n";
return 1;
}
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]);
assert(image.get() != 0);
image->readMetadata();
Exiv2::ExifData &exifData = image->exifData();
if (exifData.empty()) {
std::string error(argv[1]);
error += ": No Exif data found in the file";
throw Exiv2::Error(1, error);
}
Exiv2::ExifData::const_iterator end = exifData.end();
for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) {
const char* tn = i->typeName();
std::cout << std::setw(44) << std::setfill(' ') << std::left
<< i->key() << " "
<< "0x" << std::setw(4) << std::setfill('0') << std::right
<< std::hex << i->tag() << " "
<< std::setw(9) << std::setfill(' ') << std::left
<< (tn ? tn : "Unknown") << " "
<< std::dec << std::setw(3)
<< std::setfill(' ') << std::right
<< i->count() << " "
<< std::dec << i->value()
<< "\n";
}
return 0;
}
//catch (std::exception& e) {
//catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e.what() << "'\n";
return -1;
}
I combined response vulkanino and ThdK. My method uses the function PIGetEXIFData declared in file PropertyUtils.h that returns a binary exif. Next, this exif decoded Exiv2 library
#include <PropertyUtils.h>
#include <PIProperties.h>
#include <exif.hpp>
void printExif() {
Handle handle;
checkSPErr(PIGetEXIFData(handle));
std::string ss;
checkSPErr(HandleToString(handle, ss));
Exiv2::ExifData exifData;
Exiv2::ExifParser::decode(exifData, reinterpret_cast<const Exiv2::byte*>(ss.data()), ss.size());
Exiv2::ExifData::const_iterator end = exifData.end();
for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) {
const char* tn = i->typeName();
std::cout << std::setw(44) << std::setfill(' ') << std::left
<< i->key() << " "
<< "0x" << std::setw(4) << std::setfill('0') << std::right
<< std::hex << i->tag() << " "
<< std::setw(9) << std::setfill(' ') << std::left
<< (tn ? tn : "Unknown") << " "
<< std::dec << std::setw(3)
<< std::setfill(' ') << std::right
<< i->count() << " "
<< std::dec << i->value()
<< "\n";
}
}
So I have such log class:
#include <iostream>
#include <sstream>
#include <boost/circular_buffer.hpp>
#include <boost/foreach.hpp>
class FlushInternal;
class Log
{
public:
static FlushInternal* endl;
Log(int log_length)
{
i = 0;
messages_buffer = new boost::circular_buffer<std::string>(log_length);
}
template <class T>
Log &operator<<(const T &v)
{
current_message << v;
return *this;
}
Log &operator<<(std::ostream&(*f)(std::ostream&))
{
current_message << *f;
return *this;
}
Log &operator<<(FlushInternal*)
{
++i;
messages_buffer->push_back(current_message.str());
clean_stringstream(current_message);
is_filled();
return *this;
}
boost::circular_buffer<std::string> *messages_buffer;
private:
int i;
std::stringstream current_message;
void is_filled()
{
if (i >= messages_buffer->capacity())
{
i = 0;
BOOST_FOREACH(std::string s, *messages_buffer)
{
std::cout << ++i << ": " << s << " ;" << std::endl;
}
i = 0;
}
}
void clean_stringstream(std::stringstream &message)
{
message.flush();
message.clear();
message.seekp(0);
message.str("");
}
};
FlushInternal* Log::endl = 0;
And I can Use it like this:
#include <log.h>
int main()
{
Log l(2);
l << "message one: " << 1 << Log::endl;
l << "message two:" << " " << 2 << Log::endl;
l << "message " << "three: " << 3 << Log::endl;
l << "message" << " " << "four: " << 4 << Log::endl;
std::cin.get();
}
This would output:
1: message one: 1 ;
2: message two: 2 ;
1: message three: 3 ;
2: message four: 4 ;
As you can see I can have as many << as I want inside each log message. I want to be capable to use one instance of Log class from many threads at the same time. So I would have something like (pseudocode that compiles, runs but traces nothing.):
#include <boost/thread.hpp>
#include <log.h>
Log *l;
void fun_one()
{
*l << "message one: " << 1 << Log::endl;
*l << "message two:" << " " << 2 << Log::endl;
}
void fun_two()
{
*l << "message " << "three: " << 3 << Log::endl;
*l << "message" << " " << "four: " << 4 << Log::endl;
}
int main()
{
l = new Log(2);
boost::thread(fun_one);
boost::thread(fun_two);
std::cin.get();
}
So as you can see I want messages to be inserted into log in multythreaded function. Lo I wonder - how to make my log cclass support this?
The approach linked by trojanfoe is pretty much the canonical one. Basically create some temporary thing for the leftmost << operator, accumulate everything, and output the message in the destructor for the temporary thing.
The only question is the exact mechanics of this accumulator. The example used ostringstream, but I've seen the ofstream for the log file used directly as well (requires locking to ensure the output ends up on one line).
Creating ostringstreams is relatively expensive on some platforms, because they may need to lock and copy some internal locale related things. You could re-implement also the << operator for interesting types, but I'd test the ostringstream approach first.
A useful optimization is determine at the point of the construction of the temporary whether the trace will be emitted (e.g., whether tracing is enabled at that particular level), and not create the guts of the temporary at all in that case - all the insertion operations will be no-ops.
Here's one approach:
http://drdobbs.com/cpp/201804215
It basically creates a new ostringstream object each time you perform logging, which makes it thread safe. I can't say I'm that keen on that, as it seems a little clumsy to me.
You might have a look at the Qt logging classes as they support the << operator, however I'm not sure about thread safety.
There are 2 programs below. In the first I have striped out everything but the problem loop and when I do that it works. In the second program (still striped down from the one I am working on) I use the same logic but the sub string called for_loop_buffer never loads.
Basically I am parsing 1 string which holds a record from a cdf file. The for loop buffer is where I build each field and save it to my class. I have been spinning my wheels on this for days any help would be appreciated.
EDIT:
Here are the contents from the file the program is reading:0,Nicole 0,Debbie –
Program 1
/*******************************************************\
* Debug Version 02-b-1 - string to string build *
* *
* Saving a Person Object to file *
* This program will have a class that can save and *
* retrieve itself to and from a flat file in cdf format *
* *
* The program will accept screen input for subsequent *
* Object store call and will allow a print command that *
* will create a file of mailing labels. *
\*******************************************************/
#include <cstdlib>
#include <iostream>
#include <string>
std::string current_person = "Why does this not work? "; // CDF String version of person record from file
std::string for_loop_buffer = " "; // the substring buffer
int counter2 = 0;
int main( )
{
for (int i = 0;i <= 23;++i){
/*****************************************************************************\
* This next line apears to be the problem *
\*****************************************************************************/
for_loop_buffer[counter2] = current_person[i];
std::cout << "DEBUG - Current person " << current_person << std::endl;
std::cout << "DEBUG - current Person element " << current_person[i] << std::endl;
std::cout << "DEBUG - for Loop Buffer " << for_loop_buffer << std::endl;
std::cout << "DEBUG - for Loop Buffer element " << for_loop_buffer[counter2] << std::endl;
std::cout << "DEBUG - for Loop Buffer counter " << counter2 << std::endl;
++counter2;
} // close for
return (0);
}
Program 2
/*******************************************************\
* Debug Version 02 - Read data from a cdf file *
* *
* Saving a Person Object to file *
* This program will have a class that can save and *
* retrieve itself to and from a flat file in cdf format *
* *
* The program will accept screen input for subsequent *
* Object store call and will allow a print command that *
* will create a file of mailing labels. *
\*******************************************************/
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
/***************************************************************\
* Class Definition - person *
* *
* Member functions *
* save_person -- Save the person object to a flat file in CDF *
* get_person -- Retrives a persons data from a CDF flat file *
\***************************************************************/
// Definition of the Class
class person_class {
public:
struct person_contact {
int person_number; // System assigned not on ui
std::string first_name;
};
// Declarations for the method Prototypes
public:
// A Function that retrieves 1 person from file and
// provides it to the user
void get_person();
} person;
/*********************************************************\
* person_class::get_person -- get a data record from file *
* *
\*********************************************************/
inline void person_class::get_person()
{
// Declaration of private variables for this method
std::string ui_first_name; // User Input from Keyboard
person_contact target_person; // Name of the opbect we are filling
std::string current_person; // CDF String version of person record from file
std::cout << "Enter the First Name of the person you are looking for: ";
std::cin >> ui_first_name;
std::cout << std::endl << "Matching Records: " << std::endl;
// Open file
std::ifstream input_file("ntc_db02test.ntc");
std::cout << "DEBUG - I opened the file " << std::endl;
current_person.clear();
while (input_file.good()){
std::cout << "DEBUG - I have entered the while loop " << std::endl;
// Grab the next record from a comma delimited file
getline(input_file,current_person);
std::cout << "DEBUG - I have performed a getline " << std::endl;
std::cout << current_person << std::endl;
// I need a mechanism to build substrings
// Substring Buffer stuff
int buffer_pointer = 0; // pointer to the next position in the substring buffer
std::string for_loop_buffer =" "; // the substring buffer
for_loop_buffer.clear();
int field_index = 0; // Which field is next to load
/*******************************************************************\
* If everything went as planned I have a single CDF person record *
* in the current_person string and now all I have to do is parse *
* it and place each field in the current instance. *
\*******************************************************************/
// load the instance with the record data from the file
for (int i = 0;i < current_person.length();++i){
std::cout << "DEBUG - I am in the for loop " << std::endl;
// look for the end of the CDF field
if(current_person[i] == ','){
// Write the buffer to the next field
std::cout << "DEBUG - I found a comma " << std::endl;
switch (field_index) {
case 0:
stringstream(for_loop_buffer) >> target_person.person_number;
std::cout << "DEBUG - Field Index " << field_index << std::endl;
std::cout << "DEBUG - For Loop Buffer " << for_loop_buffer << std::endl;
std::cout << "DEBUG - Person Number " << target_person.person_number << std::endl;
break;
case 1:
stringstream(for_loop_buffer) >> target_person.first_name;
std::cout << "DEBUG - First Name " << target_person.first_name << std::endl;
break;
default:
std::cout << "This should not happen, index not functioning " << '\n';
break;
} // Close Switch
// clear the buffer
for_loop_buffer.clear(); //SE
buffer_pointer = 0;
// set up the next field load - increment the field index
++field_index; //
}else{ // close if
std::cout << "DEBUG - not a comma " << std::endl;
// If the character is not a comma
// add the character to the buffer
/*****************************************************************************\
* !!!!!!!!!!!! This next line apears to be the problem !!!!!!!!!!!!!!! *
\*****************************************************************************/
for_loop_buffer[buffer_pointer] = current_person[i];
std::cout << "DEBUG - Primary Index i " << i << std::endl;
std::cout << "DEBUG - current Person element " << current_person[i] << std::endl;
std::cout << "DEBUG - Buffer Pointer " << buffer_pointer << std::endl;
std::cout << "DEBUG - for Loop Buffer element " << for_loop_buffer[buffer_pointer] << std::endl;
std::cout << "DEBUG - for Loop Buffer " << for_loop_buffer << std::endl;
// Increment the buffer pointer
++buffer_pointer;
} // close else
} // close for
if (target_person.first_name == ui_first_name){
// Code to print out full record
std::cout << target_person.first_name << " "
<< std::endl;
} // Close if
} // Close While
input_file.close();
} // Close Class
/******************************************************************************\
* The idea this time is to do as little in the main as possible and as much *
* in the class as is appropriate. So rather than read in data and pass it to *
* the method, I will call the method and let it do its own UI reading. *
\******************************************************************************/
int main( )
{
/**********************************************************\
* Ask the user if they want to Create a new person record *
* n or find a record in the database f *
\**********************************************************/
// Set up for user input
char command = 'f';
std::cout << " What do you want to do? New Person (n) or Find Person (f) ";
std::cin >> command;
while (command == 'n' || command == 'f'){
if (command == 'n'){
std::cout << "Do Nothing" << std::endl;
} else if (command == 'f'){
person_class current_person_object;
current_person_object.get_person();
}
command = 'x';
std::cout << "I am Back in Main" << std::endl;
}
std::cout << "You entered something other than a -n- or a -f-, program terminating now" << std::endl;
return (0);
}
You are looping through the string, splitting it up on commas, however there are standard library functions that can simplify this for you. This sounds like homework, so I wont post any code answers, but here are some hints:
std::string::find_first_of will search through a string for you, and tell you where the next comma is.
std::string::substr given a position in the string and a length, will return a part of the string.
Using the above two functions in a loop you could pick out your fields in less code, that's easier to follow.
Alternatively, it would be possible to read the values straight from the stream, as the std::getline function you are using has an extra parameter to specify what character terminates the line (i.e. the comma).
Hard to see through the code, but in your "real" code you say for_loop_buffer.clear();, which is synonymous to for_loop_buffer = "";, and later I think you are accessing a member of the (now empty) string:
for_loop_buffer[buffer_pointer] = current_person[i]; // Illegal access!