Commit 191159a4 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

add support for loading lines and points from geojson

parent 60970701
Loading
Loading
Loading
Loading
+90 −0
Original line number Diff line number Diff line
@@ -185,6 +185,51 @@ ReturnCode data_load_strings(
  return expr_to_strings(expr, values);
}

ReturnCode data_load_polylines2_geojson(
    const Expr* expr,
    std::vector<PolyLine2>* data) {
  if (!expr || !expr_is_value(expr)) {
    return errorf(
        ERROR,
        "argument error; expected a filename, got: {}",
        expr_inspect(expr));
  }

  const auto& path = expr_get_value(expr);

  GeoJSONReader reader;
  reader.on_lines = [data] (const PolyLine3* polys, size_t poly_count) {
    for (size_t i = 0; i < poly_count; ++i) {
      data->emplace_back(polyline3_to_polyline2(polys[i]));
    }

    return OK;
  };

  return geojson_read_file(path, reader);
}

ReturnCode data_load_polylines2(
    const Expr* expr,
    std::vector<PolyLine2>* data) {
  if (!expr || !expr_is_list(expr) || !expr_get_list(expr)) {
    return errorf(
        ERROR,
        "argument error; expected a list, got: {}",
        expr_inspect(expr));
  }

  auto args = expr_get_list(expr);

  if (args && expr_is_value_literal(args, "geojson")) {
    return data_load_polylines2_geojson(expr_next(args), data);
  }

  return err_invalid_value(expr_inspect(expr), {
    "geojson"
  });
}

ReturnCode data_load_polys2_geojson(
    const Expr* expr,
    std::vector<Poly2>* data) {
@@ -230,6 +275,51 @@ ReturnCode data_load_polys2(
  });
}

ReturnCode data_load_points2_geojson(
    const Expr* expr,
    std::vector<vec2>* data) {
  if (!expr || !expr_is_value(expr)) {
    return errorf(
        ERROR,
        "argument error; expected a filename, got: {}",
        expr_inspect(expr));
  }

  const auto& path = expr_get_value(expr);

  GeoJSONReader reader;
  reader.on_points = [data] (const vec3* points, size_t point_count) {
    for (size_t i = 0; i < point_count; ++i) {
      data->emplace_back(points[i]);
    }

    return OK;
  };

  return geojson_read_file(path, reader);
}

ReturnCode data_load_points2(
    const Expr* expr,
    std::vector<vec2>* data) {
  if (!expr || !expr_is_list(expr) || !expr_get_list(expr)) {
    return errorf(
        ERROR,
        "argument error; expected a list, got: {}",
        expr_inspect(expr));
  }

  auto args = expr_get_list(expr);

  if (args && expr_is_value_literal(args, "geojson")) {
    return data_load_points2_geojson(expr_next(args), data);
  }

  return err_invalid_value(expr_inspect(expr), {
    "geojson"
  });
}

ReturnCode data_load(
    const Expr* expr,
    std::vector<Measure>* values) {
+8 −0
Original line number Diff line number Diff line
@@ -52,10 +52,18 @@ ReturnCode data_load_strings(
    const Expr* expr,
    std::vector<std::string>* values);

ReturnCode data_load_polylines2(
    const Expr* expr,
    std::vector<PolyLine2>* data);

ReturnCode data_load_polys2(
    const Expr* expr,
    std::vector<Poly2>* data);

ReturnCode data_load_points2(
    const Expr* expr,
    std::vector<vec2>* data);

ReturnCode data_load(
    const Expr* expr,
    std::vector<Measure>* values);
+12 −0
Original line number Diff line number Diff line
@@ -296,6 +296,18 @@ void path_add_circle(Path* path, vec2 origin, double radius) {
  path->closePath();
}

void path_add_poly_line(Path* path, const PolyLine2& line) {
  if (line.vertices.empty()) {
    return;
  }

  path->moveTo(line.vertices[0].x, line.vertices[0].y);

  for (size_t i = 1; i < line.vertices.size(); ++i) {
    path->lineTo(line.vertices[i].x, line.vertices[i].y);
  }
}

void path_add_poly_ring(Path* path, const PolyLine2& ring) {
  if (ring.vertices.empty()) {
    return;
+5 −0
Original line number Diff line number Diff line
@@ -108,6 +108,11 @@ void path_add_rectangle(Path* path, const Rectangle& rect);
 */
void path_add_circle(Path* path, vec2 origin, double radius);

/**
 * Add a polyline to a path
 */
void path_add_poly_line(Path* path, const PolyLine2& line);

/**
 * Add a polygonal ring to a path
 */
+162 −0
Original line number Diff line number Diff line
@@ -174,6 +174,152 @@ ReturnCode geojson_read_multi_polygon(
  return OK;
}

ReturnCode geojson_read_point(
    const GeoJSONReader& reader,
    const std::vector<GeoJSONCoord>& coords) {
  std::optional<vec3> point;

  if (coords.size() == 2 &&
      coords[0].rlevel == 0 &&
      coords[1].rlevel == 0) {
    point = vec3(
        coords[0].value,
        coords[1].value,
        coords[2].value);
  }

  if (coords.size() == 3 &&
      coords[0].rlevel == 0 &&
      coords[1].rlevel == 0 &&
      coords[2].rlevel == 0) {
    point = vec3(
        coords[0].value,
        coords[1].value,
        0);
  }

  if (!point) {
    return {ERROR, "invalid coordinate format for 'Point' objects"};
  }

  if (reader.on_points) {
    if (auto rc = reader.on_points(&*point, 1); !rc) {
      return rc;
    }
  }

  return OK;
}

ReturnCode geojson_read_multi_point(
    const GeoJSONReader& reader,
    const std::vector<GeoJSONCoord>& coords) {
  std::vector<vec3> points;
  for (size_t i = 0; i < coords.size(); i += 2) {
    if (i + 2 > coords.size() || coords[i].rlevel != 0 || coords[i + 1].rlevel != 1) {
      return {ERROR, "invalid coordinate format for 'MultiPoint' objects"};
    }

    if (i + 2 < coords.size() && coords[i + 2].rlevel == 1) {
      points.emplace_back(
          coords[i + 0].value,
          coords[i + 1].value,
          coords[i + 2].value);
    } else {
      points.emplace_back(
          coords[i + 0].value,
          coords[i + 1].value,
          0);
    }
  }

  if (points.empty()) {
    return {ERROR, "invalid coordinate format for 'MultiPoint' objects"};
  }

  if (reader.on_points) {
    if (auto rc = reader.on_points(points.data(), points.size()); !rc) {
      return rc;
    }
  }

  return OK;
}

ReturnCode geojson_read_line_string(
    const GeoJSONReader& reader,
    const std::vector<GeoJSONCoord>& coords) {
  PolyLine3 line;
  for (size_t i = 0; i < coords.size(); i += 2) {
    if (i + 2 > coords.size() || coords[i].rlevel != 0 || coords[i + 1].rlevel != 1) {
      return {ERROR, "invalid coordinate format for 'LineString' objects"};
    }

    if (i + 2 < coords.size() && coords[i + 2].rlevel == 1) {
      line.vertices.emplace_back(
          coords[i + 0].value,
          coords[i + 1].value,
          coords[i + 2].value);
    } else {
      line.vertices.emplace_back(
          coords[i + 0].value,
          coords[i + 1].value,
          0);
    }
  }

  if (line.vertices.empty()) {
    return {ERROR, "invalid coordinate format for 'LineString' objects"};
  }

  if (reader.on_lines) {
    if (auto rc = reader.on_lines(&line, 1); !rc) {
      return rc;
    }
  }

  return OK;
}

ReturnCode geojson_read_multi_line_string(
    const GeoJSONReader& reader,
    const std::vector<GeoJSONCoord>& coords) {
  std::vector<PolyLine3> lines;
  for (size_t i = 0; i < coords.size(); i += 2) {
    if (coords[i].rlevel == 0) {
      lines.emplace_back();
    }

    if (i + 2 > coords.size() || coords[i + 1].rlevel != 2 || lines.empty()) {
      return {ERROR, "invalid coordinate format for 'MultiLineString' objects"};
    }

    if (i + 2 < coords.size() && coords[i + 2].rlevel == 2) {
      lines.back().vertices.emplace_back(
          coords[i + 0].value,
          coords[i + 1].value,
          coords[i + 2].value);
    } else {
      lines.back().vertices.emplace_back(
          coords[i + 0].value,
          coords[i + 1].value,
          0);
    }
  }

  if (lines.empty()) {
    return {ERROR, "invalid coordinate format for 'MultiLineString' objects"};
  }

  if (reader.on_lines) {
    if (auto rc = reader.on_lines(lines.data(), lines.size()); !rc) {
      return rc;
    }
  }

  return OK;
}

ReturnCode geojson_read_object_data(
    const GeoJSONReader& reader,
    std::istream* input) {
@@ -236,6 +382,14 @@ ReturnCode geojson_read_object_data(
    return OK;
  }

  if (type == "Point") {
    return geojson_read_point(reader, coords);
  }

  if (type == "MultiPoint") {
    return geojson_read_multi_point(reader, coords);
  }

  if (type == "Polygon") {
    return geojson_read_polygon(reader, coords);
  }
@@ -244,6 +398,14 @@ ReturnCode geojson_read_object_data(
    return geojson_read_multi_polygon(reader, coords);
  }

  if (type == "LineString") {
    return geojson_read_multi_line_string(reader, coords);
  }

  if (type == "MultiLineString") {
    return geojson_read_multi_line_string(reader, coords);
  }

  return errorf(ERROR, "invalid object type: {}", type);
}

Loading