Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null2 #22

Merged
merged 6 commits into from
Apr 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: geojsonsf
Type: Package
Title: GeoJSON to Simple Feature Converter
Version: 0.3.0010
Version: 0.3.0011
Authors@R: c(
person("David", "Cooley", ,"[email protected]", role = c("aut", "cre"))
)
Expand Down
16 changes: 1 addition & 15 deletions R/scratch.R
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@


## TODO:


#
# url <- "https://data.seattle.gov/resource/pdbw-sw7q.geojson"
# sf <- sf::st_read(url, quiet = T)
# sf2 <- geojson_sf(url)
#
# library(sf)
# js <- '{"type":"FeatureCollection","features":[
# {"type":"Feature","properties":{"id":1},"geometry":{"type":"Point","coordinates":[0,0]}},
# {"type":"Feature","properties":{"id":2},"geometry":null}
# ]}'
#
# sf <- geojson_sf(js)
# ## - there needs to handle the case where the `sf` object will have any geometry type.


6 changes: 4 additions & 2 deletions inst/include/geojson_sfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ std::string attach_class(Rcpp::List& sfc, std::string geom_type,

void attach_sfc_attributes(Rcpp::List& sfc, std::string& type,
Rcpp::NumericVector& bbox,
std::set< std::string >& geometry_types);
std::set< std::string >& geometry_types,
int& nempty);

Rcpp::NumericVector start_bbox();

Expand All @@ -28,6 +29,7 @@ Rcpp::StringVector start_sfc_classes(size_t collectionCount);
Rcpp::List construct_sfc(int& sfg_objects,
Rcpp::List& sfc,
Rcpp::NumericVector& bbox,
std::set< std::string >& geometry_types);
std::set< std::string >& geometry_types,
int& nempty);

#endif
3 changes: 2 additions & 1 deletion inst/include/geojson_to_sf.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ Rcpp::List parse_feature_object(const Value& feature,
std::set< std::string >& property_keys,
Document& doc_properties,
std::map< std::string, std::string>& property_types,
bool& flatten_geometries);
bool& flatten_geometries,
int& nempty);

Rcpp::List parse_feature_collection_object(const Value& fc,
Rcpp::NumericVector& bbox,
Expand Down
2 changes: 0 additions & 2 deletions inst/include/sf_geojson.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ using namespace Rcpp;

void begin_geojson_geometry(Rcpp::String& geojson, std::string& geom_type);

void begin_geojson_geometry(Rcpp::String& geojson, Rcpp::List& sfc, std::string& geom_type);

void end_geojson_geometry(Rcpp::String& geojson, std::string& geom_type);

void add_lonlat_to_stream(Rcpp::String& geojson, Rcpp::NumericVector& points);
Expand Down
16 changes: 6 additions & 10 deletions src/geojson_sfc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ std::string attach_class(Rcpp::List& sfc,
void attach_sfc_attributes(Rcpp::List& sfc,
std::string& type,
Rcpp::NumericVector& bbox,
std::set< std::string >& geometry_types) {
std::set< std::string >& geometry_types,
int& nempty) {

std::string geometry_class = attach_class(sfc, type, geometry_types);
sfc.attr("class") = Rcpp::CharacterVector::create("sfc_" + geometry_class, "sfc");

double prec = 0;
int n_empty = 0;

// attribute::crs
Rcpp::List crs = Rcpp::List::create(Named("epsg") = geojsonsf::EPSG,
Expand All @@ -67,7 +67,7 @@ void attach_sfc_attributes(Rcpp::List& sfc,
sfc.attr("precision") = prec;

// attribute::n_empty
sfc.attr("n_empty") = n_empty;
sfc.attr("n_empty") = nempty;

// attribute::bbox
bbox.attr("class") = Rcpp::CharacterVector::create("bbox");
Expand Down Expand Up @@ -141,12 +141,7 @@ void fetch_geometries(Rcpp::List& sf, Rcpp::List& res, int& sfg_counter) {
break;
}
default: {
//Rcpp::Rcout << "debug: default geometry" << std::endl;
//Rcpp::List tmp;
//tmp.attr("class") = Rcpp::CharacterVector::create("XY","POLYGON","sfg");
Rcpp::stop("Geometry could not be determined");
//res[sfg_counter] = tmp;
//sfg_counter++;
}
}
}
Expand All @@ -156,15 +151,16 @@ void fetch_geometries(Rcpp::List& sf, Rcpp::List& res, int& sfg_counter) {
Rcpp::List construct_sfc(int& sfg_objects,
Rcpp::List& sf,
Rcpp::NumericVector& bbox,
std::set< std::string >& geometry_types) {
std::set< std::string >& geometry_types,
int& nempty) {

Rcpp::List sfc_output(sfg_objects);
std::string geom_attr;

int sfg_counter = 0;

fetch_geometries(sf, sfc_output, sfg_counter);
attach_sfc_attributes(sfc_output, geom_attr, bbox, geometry_types);
attach_sfc_attributes(sfc_output, geom_attr, bbox, geometry_types, nempty);

return sfc_output;
}
Expand Down
108 changes: 82 additions & 26 deletions src/geojson_to_sf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,52 @@ Rcpp::List parse_geometry_collection_object(const Value& val,
return geom_collection;
}

void create_null_object(Rcpp::List& sfc,
std::set< std::string >& geometry_types,
int& nempty) {
std::string geom_type;
if (geometry_types.size() == 0) {
geom_type = "Point";
} else {
geom_type = *geometry_types.begin();
}
geometry_types.insert(geom_type);
transform(geom_type.begin(), geom_type.end(), geom_type.begin(), toupper);

if (geom_type == "POINT" ) {

Rcpp::NumericVector nullObj(2, NA_REAL);
//Rcpp::NumericVector nullObj;
nullObj.attr("class") = sfg_attributes(geom_type);
sfc[0] = nullObj;

} else if (geom_type == "MULTIPOINT" || geom_type == "LINESTRING") {

Rcpp::NumericMatrix nullObj;
nullObj.attr("class") = sfg_attributes(geom_type);
sfc[0] = nullObj;

} else {

Rcpp::List nullObj;
nullObj.attr("class") = sfg_attributes(geom_type);
sfc[0] = nullObj;

}


nempty++;
}

Rcpp::List parse_feature_object(const Value& feature,
Rcpp::NumericVector& bbox,
std::set< std::string >& geometry_types,
int& sfg_objects,
std::set< std::string >& property_keys,
Document& doc_properties,
std::map< std::string, std::string>& property_types,
bool& flatten_geometries) {
bool& flatten_geometries,
int& nempty) {

validate_geometry(feature, sfg_objects);
validate_properties(feature, sfg_objects);
Expand All @@ -134,21 +172,14 @@ Rcpp::List parse_feature_object(const Value& feature,

validate_type(geometry, sfg_objects);
type = geometry["type"].GetString();
//Rcpp::Rcout << "debug: type = " << type << std::endl;

if (type == "GeometryCollection") {
sfc[0] = parse_geometry_collection_object(geometry, bbox, geometry_types, sfg_objects, flatten_geometries);
} else {
parse_geometry_object(sfc, 0, geometry, bbox, geometry_types, sfg_objects);
}
} else {
// TODO:
// insert the geometry as per teh rules followed by 'sf'
Rcpp::List nullObj;

nullObj.attr("class") = sfg_attributes("POLYGON");
sfc[0] = nullObj;
geometry_types.insert("POLYGON");
create_null_object(sfc, geometry_types, nempty);
}

if (type != "GeometryCollection") {
Expand Down Expand Up @@ -194,7 +225,8 @@ Rcpp::List parse_feature_collection_object(const Value& fc,
std::set< std::string >& property_keys,
Document& doc_properties,
std::map< std::string, std::string>& property_types,
bool& flatten_geometries) {
bool& flatten_geometries,
int& nempty) {
// a FeatureCollection MUST have members (array) called features,
validate_features(fc, sfg_objects);

Expand All @@ -208,7 +240,7 @@ Rcpp::List parse_feature_collection_object(const Value& fc,
const Value& feature = features[i];
feature_collection[i] = parse_feature_object(
feature, bbox, geometry_types, sfg_objects, property_keys, doc_properties,
property_types, flatten_geometries
property_types, flatten_geometries, nempty
);
}
return feature_collection;
Expand All @@ -226,20 +258,21 @@ void parse_geojson(const Value& v,
std::set< std::string >& property_keys,
Document& doc_properties,
std::map< std::string, std::string>& property_types,
bool& flatten_geometries) {
bool& flatten_geometries,
int& nempty) {

Rcpp::List res(1);
validate_type(v, sfg_objects);

std::string geom_type = v["type"].GetString();

if (geom_type == "Feature") {
res = parse_feature_object(v, bbox, geometry_types, sfg_objects, property_keys, doc_properties, property_types, flatten_geometries);
res = parse_feature_object(v, bbox, geometry_types, sfg_objects, property_keys, doc_properties, property_types, flatten_geometries, nempty);
sfc[i] = res;

} else if (geom_type == "FeatureCollection") {

res = parse_feature_collection_object(v, bbox, geometry_types, sfg_objects, property_keys, doc_properties, property_types, flatten_geometries);
res = parse_feature_collection_object(v, bbox, geometry_types, sfg_objects, property_keys, doc_properties, property_types, flatten_geometries, nempty);
sfc[i] = res;

} else if (geom_type == "GeometryCollection") {
Expand All @@ -266,9 +299,13 @@ void parse_geojson_object(Document& d,
std::set< std::string >& property_keys,
Document& doc_properties,
std::map< std::string, std::string>& property_types,
bool& flatten_geometries) {
bool& flatten_geometries,
int& nempty) {
const Value& v = d;
parse_geojson(v, sfc, properties, 0, bbox, geometry_types, sfg_objects, property_keys, doc_properties, property_types, flatten_geometries);
parse_geojson(
v, sfc, properties, 0, bbox, geometry_types, sfg_objects, property_keys,
doc_properties, property_types, flatten_geometries, nempty
);
}

void parse_geojson_array(Document& d,
Expand All @@ -281,9 +318,13 @@ void parse_geojson_array(Document& d,
std::set< std::string >& property_keys,
Document& doc_properties,
std::map< std::string, std::string>& property_types,
bool& flatten_geometries) {
bool& flatten_geometries,
int& nempty) {
const Value& v = d[i];
parse_geojson(v, sfc, properties, i, bbox, geometry_types, sfg_objects, property_keys, doc_properties, property_types, flatten_geometries);
parse_geojson(
v, sfc, properties, i, bbox, geometry_types, sfg_objects, property_keys,
doc_properties, property_types, flatten_geometries, nempty
);
}

Rcpp::List geojson_to_sf(const char* geojson,
Expand All @@ -293,7 +334,8 @@ Rcpp::List geojson_to_sf(const char* geojson,
std::set< std::string >& property_keys,
Document& doc_properties,
std::map< std::string, std::string>& property_types,
bool& flatten_geometries) {
bool& flatten_geometries,
int& nempty) {

Document d;
safe_parse(d, geojson);
Expand All @@ -304,15 +346,21 @@ Rcpp::List geojson_to_sf(const char* geojson,

if (d.IsObject()) {
Rcpp::List sfg(1);
parse_geojson_object(d, sfg, properties, bbox, geometry_types, sfg_objects, property_keys, doc_properties, property_types, flatten_geometries);
parse_geojson_object(
d, sfg, properties, bbox, geometry_types, sfg_objects, property_keys,
doc_properties, property_types, flatten_geometries, nempty
);
sfc[0] = sfg;

} else if (d.IsArray()) {

Rcpp::List sfgs(d.Size());

for (doc_ele = 0; doc_ele < d.Size(); doc_ele++) {
parse_geojson_array(d, sfgs, properties, doc_ele, bbox, geometry_types, sfg_objects, property_keys, doc_properties, property_types, flatten_geometries);
parse_geojson_array(
d, sfgs, properties, doc_ele, bbox, geometry_types, sfg_objects,
property_keys, doc_properties, property_types, flatten_geometries, nempty
);
}
sfc[0] = sfgs;
}
Expand Down Expand Up @@ -443,6 +491,7 @@ Rcpp::List create_sfc(Rcpp::StringVector geojson, bool& flatten_geometries) {
// iterate over the geojson
int n = geojson.size();
int sfg_objects = 0; // keep track of number of objects
int nempty = 0;
//int row_index;

// Attributes to keep track of along the way
Expand All @@ -456,10 +505,13 @@ Rcpp::List create_sfc(Rcpp::StringVector geojson, bool& flatten_geometries) {
Rcpp::List sfc(n);

for (int geo_ele = 0; geo_ele < n; geo_ele++ ){
sfc[geo_ele] = geojson_to_sf(geojson[geo_ele], bbox, geometry_types, sfg_objects, property_keys, doc_properties, property_types, flatten_geometries);
sfc[geo_ele] = geojson_to_sf(
geojson[geo_ele], bbox, geometry_types, sfg_objects, property_keys,
doc_properties, property_types, flatten_geometries, nempty
);
}

return construct_sfc(sfg_objects, sfc, bbox, geometry_types);
return construct_sfc(sfg_objects, sfc, bbox, geometry_types, nempty);
}

// [[Rcpp::export]]
Expand Down Expand Up @@ -494,7 +546,8 @@ Rcpp::List generic_geojson_to_sf(Rcpp::StringVector geojson, bool& flatten_geome
// iterate over the geojson
int n = geojson.size();
int sfg_objects = 0; // keep track of number of objects
int row_index;
int row_index = 0;
int nempty = 0;

// Attributes to keep track of along the way
Rcpp::NumericVector bbox = start_bbox();
Expand All @@ -507,11 +560,14 @@ Rcpp::List generic_geojson_to_sf(Rcpp::StringVector geojson, bool& flatten_geome
Rcpp::List sfc(n);

for (int geo_ele = 0; geo_ele < n; geo_ele++ ){
sfc[geo_ele] = geojson_to_sf(geojson[geo_ele], bbox, geometry_types, sfg_objects, property_keys, doc_properties, property_types, flatten_geometries);
sfc[geo_ele] = geojson_to_sf(
geojson[geo_ele], bbox, geometry_types, sfg_objects, property_keys,
doc_properties, property_types, flatten_geometries, nempty
);
}


Rcpp::List res = construct_sfc(sfg_objects, sfc, bbox, geometry_types);
Rcpp::List res = construct_sfc(sfg_objects, sfc, bbox, geometry_types, nempty);
return construct_sf(res, property_keys, property_types, doc_properties, sfg_objects, row_index);
}

Expand Down
Loading