Skip to content

Commit

Permalink
support user defined network attributes (#69)
Browse files Browse the repository at this point in the history
* node osm attributes

* finish node and link

* finish poi

* finish python api

* use string in parsing config
jiawlu authored Jan 10, 2025
1 parent b76cd42 commit 92a5404
Showing 12 changed files with 218 additions and 39 deletions.
6 changes: 5 additions & 1 deletion dev/osm2gmns_dev.cpp
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
#include <iostream>
#include <string>

#include "config.h"
#include "functions.h"
#include "io.h"
#include "networks.h"
@@ -30,11 +31,14 @@ int main(int /*argc*/, char* /*argv*/[]) {
// const std::string map_filename = "map_sub.osm";
const std::string map_filename = "Columbus, Franklin County, Ohio, United States.pbf";

const auto* osm_parsing_config =
new OsmParsingConfig{{"highway", "ref"}, {"sidewalk", "maxspeed"}, {"building", "type"}};

Network* network = getNetFromFile(map_folder / map_filename,
{ModeType::AUTO, ModeType::BIKE, ModeType::RAILWAY, ModeType::AEROWAY},
{HighWayLinkType::MOTORWAY, HighWayLinkType::TRUNK, HighWayLinkType::PRIMARY,
HighWayLinkType::SECONDARY, HighWayLinkType::TERTIARY},
{HighWayLinkType::RESIDENTIAL}, true, 1.0, true);
{HighWayLinkType::RESIDENTIAL}, true, 1.0, osm_parsing_config, true);

// consolidateComplexIntersections(network, true);

15 changes: 14 additions & 1 deletion osm2gmns/osm2gmns.py
Original file line number Diff line number Diff line change
@@ -37,6 +37,9 @@ def initlib():
ctypes.POINTER(ctypes.c_char_p), ctypes.c_size_t,
ctypes.POINTER(ctypes.c_char_p), ctypes.c_size_t,
ctypes.c_bool, ctypes.c_float,
ctypes.POINTER(ctypes.c_char_p), ctypes.c_size_t,
ctypes.POINTER(ctypes.c_char_p), ctypes.c_size_t,
ctypes.POINTER(ctypes.c_char_p), ctypes.c_size_t,
ctypes.c_bool]
oglib.getNetFromFilePy.restype = ctypes.c_void_p

@@ -79,6 +82,7 @@ def _checkStringToTuple(arg_val):
return (arg_val,) if isinstance(arg_val, str) else arg_val

def getNetFromFile(filename='map.osm', mode_types=('auto',), link_types=(), connector_link_types=(), POI=False, POI_sampling_ratio=1.0,
osm_node_attributes=(), osm_link_attributes=(), osm_poi_attributes=(),
strict_boundary=True, **kwargs):
network = Network()

@@ -91,15 +95,24 @@ def getNetFromFile(filename='map.osm', mode_types=('auto',), link_types=(), conn

link_types_byte_string = [link_type.encode() for link_type in _checkStringToTuple(link_types)]
link_types_arr = (ctypes.c_char_p * len(link_types_byte_string))(*link_types_byte_string)

connector_link_types_byte_string = [link_type.encode() for link_type in _checkStringToTuple(connector_link_types)]
connector_link_types_arr = (ctypes.c_char_p * len(connector_link_types_byte_string))(*connector_link_types_byte_string)

osm_node_attributes_byte_string = [attr.encode() for attr in _checkStringToTuple(osm_node_attributes)]
osm_node_attributes_arr = (ctypes.c_char_p * len(osm_node_attributes_byte_string))(*osm_node_attributes_byte_string)
osm_link_attributes_byte_string = [attr.encode() for attr in _checkStringToTuple(osm_link_attributes)]
osm_link_attributes_arr = (ctypes.c_char_p * len(osm_link_attributes_byte_string))(*osm_link_attributes_byte_string)
osm_poi_attributes_byte_string = [attr.encode() for attr in _checkStringToTuple(osm_poi_attributes)]
osm_poi_attributes_arr = (ctypes.c_char_p * len(osm_poi_attributes_byte_string))(*osm_poi_attributes_byte_string)

network.cnet = oglib.getNetFromFilePy(filename.encode(),
mode_types_arr, len(mode_types_arr),
link_types_arr, len(link_types_arr),
connector_link_types_arr, len(connector_link_types_arr),
POI, POI_sampling_ratio,
osm_node_attributes_arr, len(osm_node_attributes_arr),
osm_link_attributes_arr, len(osm_link_attributes_arr),
osm_poi_attributes_arr, len(osm_poi_attributes_arr),
strict_boundary)
return network

31 changes: 29 additions & 2 deletions osm2gmns_lib.cpp
Original file line number Diff line number Diff line change
@@ -12,7 +12,9 @@
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

#include "src/config.h"
#include "src/functions.h"
#include "src/io.h"
#include "src/networks.h"
@@ -54,6 +56,24 @@ absl::flat_hash_set<ModeType> parseModeTypes(const char** mode_types_val, size_t
return mode_types;
}

std::vector<const char*> parseChars(const char** chars_val, size_t chars_len) {
std::vector<const char*> char_vector;
char_vector.reserve(chars_len);
for (size_t idx = 0; idx < chars_len; ++idx) {
char_vector.push_back(chars_val[idx]); // NOLINT
}
return char_vector;
}

std::vector<std::string> parseCharArraysToStringVector(const char** chars_val, size_t chars_len) {
std::vector<std::string> char_vector;
char_vector.reserve(chars_len);
for (size_t idx = 0; idx < chars_len; ++idx) {
char_vector.emplace_back(chars_val[idx]); // NOLINT
}
return char_vector;
}

template <typename T>
struct StrNumDict {
const char* key;
@@ -87,13 +107,20 @@ C_API void releaseNetworkMemoryPy(Network* network) { delete network; };
C_API Network* getNetFromFilePy(const char* osm_filepath, const char** mode_types_val, size_t mode_types_len,
const char** link_types_val, size_t link_types_len,
const char** connector_link_types_val, size_t connector_link_types_len, bool POI,
float POI_sampling_ratio, bool strict_boundary) {
float POI_sampling_ratio, const char** osm_node_attributes_val,
size_t osm_node_attributes_len, const char** osm_link_attributes_val,
size_t osm_link_attributes_len, const char** osm_poi_attributes_val,
size_t osm_poi_attributes_len, bool strict_boundary) {
const absl::flat_hash_set<ModeType> mode_types = parseModeTypes(mode_types_val, mode_types_len);
const absl::flat_hash_set<HighWayLinkType> link_types = parseLinkTypes(link_types_val, link_types_len);
const absl::flat_hash_set<HighWayLinkType> connector_link_types =
parseLinkTypes(connector_link_types_val, connector_link_types_len);
auto* osm_parsing_config =
new OsmParsingConfig{parseCharArraysToStringVector(osm_node_attributes_val, osm_node_attributes_len),
parseCharArraysToStringVector(osm_link_attributes_val, osm_link_attributes_len),
parseCharArraysToStringVector(osm_poi_attributes_val, osm_poi_attributes_len)};
Network* network = getNetFromFile(osm_filepath, mode_types, link_types, connector_link_types, POI, POI_sampling_ratio,
strict_boundary);
osm_parsing_config, strict_boundary);
return network;
};

17 changes: 17 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Created by Jiawei Lu on 1/4/25.
//

#ifndef OSM2GMNS_CONFIG_H
#define OSM2GMNS_CONFIG_H

#include <string>
#include <vector>

struct OsmParsingConfig {
std::vector<std::string> osm_node_attributes;
std::vector<std::string> osm_link_attributes;
std::vector<std::string> osm_poi_attributes;
};

#endif // OSM2GMNS_CONFIG_H
8 changes: 5 additions & 3 deletions src/functions.cpp
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
#include <filesystem>
#include <vector>

#include "config.h"
#include "io.h"
#include "networks.h"
#include "osmconfig.h"
@@ -16,7 +17,7 @@
Network* getNetFromFile(const std::filesystem::path& osm_filepath, const absl::flat_hash_set<ModeType>& mode_types,
const absl::flat_hash_set<HighWayLinkType>& link_types,
const absl::flat_hash_set<HighWayLinkType>& connector_link_types, bool POI,
float POI_sampling_ratio, bool strict_boundary) {
float POI_sampling_ratio, const OsmParsingConfig* osm_parsing_config, bool strict_boundary) {
absl::flat_hash_set<HighWayLinkType> connector_link_types_(connector_link_types);
if (!connector_link_types_.empty()) {
if (link_types.empty()) {
@@ -40,9 +41,10 @@ Network* getNetFromFile(const std::filesystem::path& osm_filepath, const absl::f
}
}
LOG(INFO) << "loading data from osm file";
auto* osmnet = new OsmNetwork(osm_filepath, mode_types, link_types, connector_link_types_, POI, strict_boundary);
auto* osmnet = new OsmNetwork(osm_filepath, mode_types, link_types, connector_link_types_, POI, osm_parsing_config,
strict_boundary);
LOG(INFO) << "start to build network";
auto* network = new Network(osmnet, link_types, connector_link_types_, POI, POI_sampling_ratio);
auto* network = new Network(osmnet, link_types, connector_link_types_, POI, POI_sampling_ratio, osm_parsing_config);
LOG(INFO) << "build network done";
return network;
};
4 changes: 3 additions & 1 deletion src/functions.h
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
#include <cstdint>
#include <filesystem>

#include "config.h"
#include "networks.h"
#include "osmconfig.h"

@@ -20,7 +21,8 @@ Network* getNetFromFile(const std::filesystem::path& osm_filepath,
const absl::flat_hash_set<ModeType>& mode_types = {ModeType::AUTO},
const absl::flat_hash_set<HighWayLinkType>& link_types = {},
const absl::flat_hash_set<HighWayLinkType>& connector_link_types = {}, bool POI = false,
float POI_sampling_ratio = 1.0, bool strict_boundary = true);
float POI_sampling_ratio = 1.0, const OsmParsingConfig* osm_parsing_config = nullptr,
bool strict_boundary = true);

void consolidateComplexIntersections(Network* network, bool auto_identify = false,
const std::filesystem::path& intersection_file = "",
40 changes: 32 additions & 8 deletions src/io.cpp
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@
#include "networks.h"
#include "osmconfig.h"

constexpr int COORDINATE_OUTPUT_PRECISION = 6;
constexpr int COORDINATE_OUTPUT_PRECISION = 7;
constexpr int LENGTH_OUTPUT_PRECISION = 2;
constexpr int AREA_OUTPUT_PRECISION = 1;

@@ -94,7 +94,12 @@ void outputNetToCSV(const Network* network, const std::filesystem::path& output_
LOG(ERROR) << "Cannot open file " << node_filepath;
return;
}
node_file << "name,node_id,osm_node_id,ctrl_type,x_coord,y_coord,is_boundary,activity_type,poi_id,zone_id,notes\n";
node_file << "name,node_id,osm_node_id,ctrl_type,x_coord,y_coord";
for (const std::string& attr_name : network->osmParsingConfig()->osm_node_attributes) {
node_file << "," << attr_name;
}
node_file << ",is_boundary,activity_type,poi_id,zone_id,notes\n";

for (const Node* node : network->nodeVector()) {
const std::string& name = absl::StrContains(node->name(), ',') ? "\"" + node->name() + "\"" : node->name();
const std::string& ctrl_type = node->isSignalized() ? "signal" : "";
@@ -105,8 +110,11 @@ void outputNetToCSV(const Network* network, const std::filesystem::path& output_
node->activityType().has_value() ? getHighWayLinkTypeStr(node->activityType().value()) : ""; // NOLINT
node_file << name << "," << node->nodeId() << "," << node->osmNodeId() << "," << ctrl_type << "," << std::fixed
<< std::setprecision(COORDINATE_OUTPUT_PRECISION) << node->geometry()->getX() << ","
<< node->geometry()->getY() << std::defaultfloat << "," << boundary << "," << activity_type << ",,"
<< zone_id << ",\n";
<< node->geometry()->getY() << std::defaultfloat;
for (const std::string& attr_value : node->osmAttributes()) {
node_file << "," << attr_value;
}
node_file << "," << boundary << "," << activity_type << ",," << zone_id << ",\n";
}
node_file.close();

@@ -117,7 +125,11 @@ void outputNetToCSV(const Network* network, const std::filesystem::path& output_
return;
}
link_file << "link_id,name,osm_way_id,from_node_id,to_node_id,directed,geometry,dir_flag,length,facility_type,link_"
"type,free_speed,free_speed_raw,lanes,capacity,allowed_uses,toll,notes\n";
"type,free_speed,free_speed_raw,lanes,capacity,allowed_uses,toll";
for (const std::string& attr_name : network->osmParsingConfig()->osm_link_attributes) {
link_file << "," << attr_name;
}
link_file << ",notes\n";
for (const Link* link : network->linkVector()) {
const std::string& name = absl::StrContains(link->name(), ',') ? "\"" + link->name() + "\"" : link->name();
const std::string& facility_type =
@@ -153,7 +165,11 @@ void outputNetToCSV(const Network* network, const std::filesystem::path& output_
<< link->toNode()->nodeId() << ",1,\"" << link->geometry()->toString() << "\",1," << std::fixed
<< std::setprecision(LENGTH_OUTPUT_PRECISION) << link->length() << "," << facility_type << "," << type_no
<< "," << free_speed << "," << free_speed_raw << "," << lanes << "," << capacity << "," << allowed_uses
<< "," << toll << ",\n";
<< "," << toll;
for (const std::string& attr_value : link->osmAttributes()) {
link_file << "," << attr_value;
}
link_file << ",\n";
}
link_file.close();

@@ -166,7 +182,11 @@ void outputNetToCSV(const Network* network, const std::filesystem::path& output_
std::cout << "Cannot open file " << poi_filepath;
return;
}
poi_file << "name,poi_id,osm_way_id,osm_relation_id,building,amenity,leisure,way,geometry,centroid,area,area_ft2\n";
poi_file << "name,poi_id,osm_way_id,osm_relation_id,building,amenity,leisure,way,geometry,centroid,area,area_ft2";
for (const std::string& attr_name : network->osmParsingConfig()->osm_poi_attributes) {
poi_file << "," << attr_name;
}
poi_file << "\n";
for (const POI* poi : network->poiVector()) {
const std::string& name = absl::StrContains(poi->name(), ',') ? "\"" + poi->name() + "\"" : poi->name();
const std::string osm_way_id =
@@ -180,7 +200,11 @@ void outputNetToCSV(const Network* network, const std::filesystem::path& output_
poi_file << name << "," << poi->poiId() << "," << osm_way_id << "," << osm_relation_id << "," << building << ","
<< amenity << "," << leisure << ",,\"" << poi->geometry()->toString() << "\",\""
<< poi->centroidGeometry()->toString() << "\"," << std::fixed << std::setprecision(AREA_OUTPUT_PRECISION)
<< poi->area() << ",\n";
<< poi->area() << ",";
for (const std::string& attr_value : poi->osmAttributes()) {
poi_file << "," << attr_value;
}
poi_file << "\n";
}
poi_file.close();

20 changes: 16 additions & 4 deletions src/networks.cpp
Original file line number Diff line number Diff line change
@@ -36,7 +36,10 @@
#include "utils.h"

Node::Node(const OsmNode* osm_node, const geos::geom::GeometryFactory* factory)
: osm_nodes_({osm_node}), name_(osm_node->name()), is_signalized_(osm_node->isSignalized()) {
: osm_nodes_({osm_node}),
name_(osm_node->name()),
is_signalized_(osm_node->isSignalized()),
osm_attributes_(osm_node->osmAttributes()) {
geometry_ = factory->createPoint(geos::geom::Coordinate(osm_node->getX(), osm_node->getY()));
}

@@ -87,6 +90,7 @@ std::string Node::osmNodeId() const {
const std::string& Node::name() const { return name_; }
bool Node::isSignalized() const { return is_signalized_; }
const std::unique_ptr<geos::geom::Point>& Node::geometry() const { return geometry_; }
const std::vector<std::string>& Node::osmAttributes() const { return osm_attributes_; };
std::optional<NetIdType> Node::zoneId() const { return zone_id_; }
std::optional<int16_t> Node::boundary() const { return boundary_; }
std::optional<HighWayLinkType> Node::activityType() const { return activity_type_; }
@@ -104,7 +108,8 @@ Link::Link(const OsmWay* osm_way, const std::vector<OsmNode*>& osm_nodes, bool f
free_speed_(osm_way->maxSpeed()),
free_speed_raw_(osm_way->maxSpeedRaw()),
allowed_mode_types_(osm_way->allowedModeTypes()),
toll_(osm_way->toll()) {
toll_(osm_way->toll()),
osm_attributes_(osm_way->osmLinkAttributes()) {
if (osm_nodes.size() < 2) {
return;
}
@@ -175,6 +180,7 @@ std::string Link::freeSpeedRaw() const { return free_speed_raw_; }
std::optional<int32_t> Link::capacity() const { return capacity_; }
const std::vector<ModeType>& Link::allowedModeTypes() const { return allowed_mode_types_; }
const std::string& Link::toll() const { return toll_; }
const std::vector<std::string>& Link::osmAttributes() const { return osm_attributes_; }

void Link::setLinkId(NetIdType link_id) { link_id_ = link_id; }
void Link::setFromNode(Node* from_node) { from_node_ = from_node; }
@@ -190,6 +196,7 @@ POI::POI(const OsmWay* osm_way, std::unique_ptr<geos::geom::Polygon> geometry)
building_(osm_way->building()),
amenity_(osm_way->amenity()),
leisure_(osm_way->leisure()),
osm_attributes_(osm_way->osmPoiAttributes()),
geometry_(std::move(geometry)),
centroid_geometry_(std::move(geometry_->getCentroid())),
geometry_utm_(std::move(projectGeometryToUTM(geometry_.get(), geometry_->getFactory()))) {}
@@ -200,6 +207,7 @@ POI::POI(const OsmRelation* osm_relation, std::unique_ptr<geos::geom::MultiPolyg
building_(osm_relation->building()),
amenity_(osm_relation->amenity()),
leisure_(osm_relation->leisure()),
osm_attributes_(osm_relation->osmAttributes()),
geometry_(std::move(geometry)),
centroid_geometry_(std::move(geometry_->getCentroid())),
geometry_utm_(std::move(projectGeometryToUTM(geometry_.get(), geometry_->getFactory()))) {}
@@ -211,6 +219,7 @@ std::optional<OsmIdType> POI::osmRelationId() const { return osm_relation_id_; }
const std::string& POI::building() const { return building_; }
const std::string& POI::amenity() const { return amenity_; }
const std::string& POI::leisure() const { return leisure_; }
const std::vector<std::string>& POI::osmAttributes() const { return osm_attributes_; }
const std::unique_ptr<geos::geom::Geometry>& POI::geometry() const { return geometry_; }
const std::unique_ptr<geos::geom::Point>& POI::centroidGeometry() const { return centroid_geometry_; }
double POI::area() const { return geometry_utm_ != nullptr ? geometry_utm_->getArea() : 0.0; }
@@ -226,12 +235,14 @@ const std::unique_ptr<geos::geom::Geometry>& Zone::geometry() const { return geo
Intersection::Intersection() = default;

Network::Network(OsmNetwork* osmnet, absl::flat_hash_set<HighWayLinkType> link_types,
absl::flat_hash_set<HighWayLinkType> connector_link_types, bool POI, float POI_sampling_ratio)
absl::flat_hash_set<HighWayLinkType> connector_link_types, bool POI, float POI_sampling_ratio,
const OsmParsingConfig* osm_parsing_config)
: osmnet_(osmnet),
link_types_(std::move(link_types)),
connector_link_types_(std::move(connector_link_types)),
POI_(POI),
POI_sampling_ratio_(POI_sampling_ratio) {
POI_sampling_ratio_(POI_sampling_ratio),
osm_parsing_config_(osm_parsing_config) {
factory_ = geos::geom::GeometryFactory::create();
if (osmnet_->boundary().has_value()) {
boundary_ = static_cast<std::unique_ptr<geos::geom::Polygon>>(osmnet_->boundary().value()->clone()); // NOLINT
@@ -268,6 +279,7 @@ Network::~Network() {
}

bool Network::poi() const { return POI_; }
const OsmParsingConfig* Network::osmParsingConfig() const { return osm_parsing_config_; }
size_t Network::numberOfNodes() const { return node_vector_.size(); }
size_t Network::numberOfLinks() const { return link_vector_.size(); }
const std::vector<Node*>& Network::nodeVector() const { return node_vector_; }
Loading
Oops, something went wrong.

0 comments on commit 92a5404

Please sign in to comment.