#svg #gis #graphics

geo-svg-io

SVG和geo类型之间的转换功能

2次发布

0.1.1 2020年4月22日
0.1.0 2020年4月15日

#138 in 地理空间

每月 21次下载

MIT 许可证

80KB
1.5K SLoC

rust-geo-svg

SVG和geo类型之间的转换功能。

SVG到几何形状

此包提供了一组函数,用于读取包含SVG元素的字符串或d字符串,并将其解析为几何形状。

svg_to_geometry(svg: &str)

注意此函数不会解析完整的SVG字符串(例如,<svg xmlns="http://www.w3.org/2000/svg"><path d="M0 0L10 0L10 10L0 10Z"/></svg>),它只会解析单个形状元素(例如,<path d="M0 0L10 0L10 10L0 10Z"/>)。以下SVG元素受支持,并生成指定的几何类型

  • <path> → 自动检测类型的几何形状
  • <polygon> → 多边形
  • <polyline> → 线串
  • <rect> → 多边形
  • <line> → 线

示例

use geo_types::{ Polygon, polygon };
use geo_svg_io::geo_svg_reader::svg_to_geometry;

let poly: Polygon<f64> = polygon!(
    exterior: [
        (x: 0.0_f64, y: 0.0),
        (x: 0.0, y: 60.0),
        (x: 60.0, y: 60.0),
        (x: 60.0, y: 0.0),
        (x: 0.0, y: 0.0),],
    interiors:[[
        (x: 10.0, y: 10.0),
        (x: 40.0, y: 1.0),
        (x: 40.0, y: 40.0),
        (x: 10.50, y: 40.0),
        (x: 10.0, y: 10.0),]
        ]
    );
let svg_string =
    String::from(r#"<path d="M0 0L0 60L60 60L60 0L0 0M10 10L40 1L40 40L10.5 40L10 10"/>"#);

let parsed_svg = svg_to_geometry(&svg_string);
assert!(parsed_svg.is_ok());
let parsed_poly = parsed_svg.ok().unwrap().into_polygon();
assert!(parsed_poly.is_some());
assert_eq!(poly, parsed_poly.unwrap());
use geo_types::{ Polygon, polygon };
use geo_svg_io::geo_svg_reader::svg_to_geometry;

let poly: Polygon<f64> = polygon!(
    exterior: [
        (x: 0.0_f64, y: 0.0),
        (x: 0.0, y: 60.0),
        (x: 60.0, y: 60.0),
        (x: 60.0, y: 0.0),
        (x: 0.0, y: 0.0),],
    interiors:[]
    );
let svg_string = String::from(r#"<polygon points="0, 0 60, 0 60, 60 0, 60 0, 0"/>"#);

let parsed_svg = svg_to_geometry(&svg_string);
assert!(parsed_svg.is_ok());
let parsed_poly = parsed_svg.ok().unwrap().into_polygon();
assert!(parsed_poly.is_some());
assert_eq!(poly, parsed_poly.unwrap());

svg_to_geometry_collection(svg: &str)

注意此函数不会解析完整的SVG字符串(例如,<svg xmlns="http://www.w3.org/2000/svg"><path d="M0 0L10 0L10 10L0 10Z"/></svg>),它只会解析单个形状元素(例如,<path d="M0 0L10 0L10 10L0 10Z"/>)。以下SVG元素受支持,并生成指定的几何类型

  • <path> → 几何形状集合
  • <polygon> → 包含单个多边形的几何形状集合
  • <polyline> → 包含单个线串的几何形状集合
  • <rect> → 包含单个多边形的几何形状集合
  • <line> → 包含单个线的几何形状集合

示例

use geo_types::{ Polygon, polygon };
use geo_svg_io::geo_svg_reader::svg_to_geometry_collection;

let poly: Polygon<f64> = polygon!(
        exterior: [
            (x: 0.0_f64, y: 0.0),
            (x: 0.0, y: 60.0),
            (x: 60.0, y: 60.0),
            (x: 60.0, y: 0.0),
            (x: 0.0, y: 0.0),],
        interiors:[[
            (x: 10.0, y: 10.0),
            (x: 40.0, y: 1.0),
            (x: 40.0, y: 40.0),
            (x: 10.50, y: 40.0),
            (x: 10.0, y: 10.0),]
            ]
        )
        .into();
let svg_string =
            String::from(r#"<path d="M0 0L0 60L60 60L60 0L0 0M10 10L40 1L40 40L10.5 40L10 10"/>"#);

let parsed_svg = svg_to_geometry_collection(&svg_string);
assert!(parsed_svg.is_ok());

// Unwrap the GeometryCollection result
let geom = parsed_svg.ok().unwrap();
assert_eq!(1, geom.0.len());

// Read the geometry as a Polygon
let pl = geom.0[0].clone().into_polygon();
assert_eq!(true, pl.is_some());
assert_eq!(poly, pl.unwrap());
use geo_types::{ Polygon, polygon };
use geo_svg_io::geo_svg_reader::svg_to_geometry;

let poly: Polygon<f64> = polygon!(
        exterior: [
            (x: 0.0_f64, y: 0.0),
            (x: 0.0, y: 60.0),
            (x: 60.0, y: 60.0),
            (x: 60.0, y: 0.0),
            (x: 0.0, y: 0.0),],
        interiors:[]
        )
        .into();

let svg_string = String::from(r#"<polygon points="0, 0 60, 0 60, 60 0, 60 0, 0"/>"#);

let parsed_svg = svg_to_geometry_collection(&svg_string);
assert!(parsed_svg.is_ok());

// Unwrap the GeometryCollection result
let geom = parsed_svg.ok().unwrap();
assert_eq!(1, geom.0.len());

// Read the geometry as a Polygon
let pl = geom.0[0].clone().into_polygon();
assert_eq!(true, pl.is_some());
assert_eq!(poly, pl.unwrap());

svg_d_path_to_geometry(svg: &str)

<path>元素的d字符串可以直接通过svg_d_path_to_geometry(svg: &str)函数解析为几何形状。输出始终为几何形状集合。

示例

use geo_svg_io::geo_svg_reader::svg_d_path_to_geometry_collection;
use geo_types::polygon;

let poly = polygon!(
        exterior: [
            (x: 0.0, y: 0.0),
            (x: 0.0, y: 60.0),
            (x: 60.0, y: 60.0),
            (x: 60.0, y: 0.0),
            (x: 0.0, y: 0.0),],
        interiors:[[
            (x: 10.0, y: 10.0),
            (x: 40.0, y: 1.0),
            (x: 40.0, y: 40.0),
            (x: 10.50, y: 40.0),
            (x: 10.0, y: 10.0),]
            ]
        );

let svg_string = String::from("M0 0l0 60l60 0L60 0L0 0M10 10L40 1L40 40L10.5 40L10 10");
let parsed_svg = svg_d_path_to_geometry(&svg_string);
assert!(parsed_svg.is_ok());
let pl = parsed_svg.ok().unwrap().into_polygon();
assert!(pl.is_some());
assert_eq!(pl.unwrap(), poly);

svg_d_path_to_geometry_collection(svg: &str)

可以将<path>元素的d字符串直接解析为GeometryCollection,这是通过svg_d_path_to_geometry_collection(svg: &str)函数实现的。输出总是GeometryCollection。

示例

use geo_svg_io::geo_svg_reader::svg_d_path_to_geometry_collection;
use geo_types::polygon;

let poly = polygon!(
        exterior: [
            (x: 0.0, y: 0.0),
            (x: 0.0, y: 60.0),
            (x: 60.0, y: 60.0),
            (x: 60.0, y: 0.0),
            (x: 0.0, y: 0.0),],
        interiors:[[
            (x: 10.0, y: 10.0),
            (x: 40.0, y: 1.0),
            (x: 40.0, y: 40.0),
            (x: 10.50, y: 40.0),
            (x: 10.0, y: 10.0),]
            ]
        );

let svg_string = String::from("M0 0l0 60l60 0L60 0L0 0M10 10L40 1L40 40L10.5 40L10 10");
let parsed_svg = svg_d_path_to_geometry_collection(&svg_string);
assert!(parsed_svg.is_ok());

// Unwrap the GeometryCollection result
let geom = parsed_svg.ok().unwrap();
assert_eq!(1, geom.0.len());

// Read the geometry as a Polygon
let pl = geom.0[0].clone().into_polygon();
assert_eq!(true, pl.is_some());
assert_eq!(pl.unwrap(), poly);

错误处理

这两个函数都返回一个Result,它可能包含解析后的Geometry或SvgError枚举类型的Error。错误可能源于传递了不支持的SVG元素类型,SVG元素格式不正确,或者无法从提供的字符串中解析出float

Geometry转SVG

此包提供了两个特质,用于将Geometry转换为SVG。请注意,对<path> d-字符串的解析是简化的。它在曲线上绘制了100个点。

待办事项 将此功能更新为使用递归函数来创建点,直到它们共线(足够多)。

ToSvg

使用to_svg()从任何Geometry类型生成最简单的SVG元素

  • 多边形 → <path>
  • LineString → <polyline>
  • Line → <line>
  • 三角形 → <polygon>带有三个点
  • 矩形 → <rect>带有xywidthheight

复杂的Geometry类型将返回多个通过newline分隔的SVG元素

  • GeometryCollection → 与包含的单独Geometry对应的newline分隔的SVG元素
  • MultiPolygon → newline分隔的元素
  • MultiLineString → newline分隔的元素

示例

use geo_types::{ MultiPolygon, polygon };
use geo_svg_io::geo_svg_writer::ToSvg;

let poly1 = polygon![
            (x: 1.0, y: 1.0),
            (x: 4.0, y: 1.0),
            (x: 4.0, y: 4.0),
            (x: 1.0, y: 4.0),
            (x: 1.0, y: 1.0),
        ];

let poly2 = polygon!(
        exterior: [
            (x: 0.0, y: 0.0),
            (x: 6.0, y: 0.0),
            (x: 6.0, y: 6.0),
            (x: 0.0, y: 6.0),
            (x: 0.0, y: 0.0),],
        interiors:[[
            (x: 1.0, y: 1.0),
            (x: 4.0, y: 1.0),
            (x: 4.0, y: 4.0),
            (x: 1.50, y: 4.0),
            (x: 1.0, y: 1.0),]
            ]
        );

let mp = MultiPolygon(vec![poly1, poly2]);
let wkt_out = mp.to_svg();
let expected = String::from(
            r#"<path d="M1 1L4 1L4 4L1 4L1 1"/>
<path d="M0 0L6 0L6 6L0 6L0 0M1 1L4 1L4 4L1.5 4L1 1"/>"#,
        );

assert_eq!(wkt_out, expected);

ToSvgString

使用to_svg_string()从任何Geometry类型生成包含该几何所有点的SVG d字符串,这可以用于SVG路径元素

示例

use geo_types::{polygon, MultiPolygon};
use geo_svg_io::geo_svg_writer::ToSvgString;

let poly1 = polygon![
            (x: 1.0, y: 1.0),
            (x: 4.0, y: 1.0),
            (x: 4.0, y: 4.0),
            (x: 1.0, y: 4.0),
            (x: 1.0, y: 1.0),
        ];

let poly2 = polygon!(
        exterior: [
            (x: 0.0, y: 0.0),
            (x: 6.0, y: 0.0),
            (x: 6.0, y: 6.0),
            (x: 0.0, y: 6.0),
            (x: 0.0, y: 0.0),],
        interiors:[[
            (x: 1.0, y: 1.0),
            (x: 4.0, y: 1.0),
            (x: 4.0, y: 4.0),
            (x: 1.50, y: 4.0),
            (x: 1.0, y: 1.0),]
            ]
        );

let mp = MultiPolygon(vec![poly1, poly2]);
let wkt_out = mp.to_svg_string();
let expected = String::from(
    "M1 1L4 1L4 4L1 4L1 1M0 0L6 0L6 6L0 6L0 0M1 1L4 1L4 4L1.5 4L1 1"
);
assert_eq!(wkt_out, expected);

类似项目

有关提供从Rust geo类型构建SVG的更高层次功能的类似项目,请参阅https://github.com/lelongg/geo-svg

依赖项

~4.5MB
~76K SLoC