Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to check geometry type from geo_types

I’m new to Rust and I’m still struggling with the borrowing concept in combination with the TryFrom function from the geo_types crate.

I basically want to do different things depending on the actual Geometry type:

use geo_types::{Geometry, Point, LineString};

fn some_func(g : Geometry<f64>) {
    if let Ok(p) = Point::try_from(g) {
        print!("POINT");
    } else if let Ok(ls) = LineString::try_from(g) { 
        print!("LINESTRING");
    } else {
        print!("UNKNOWN");
    }
}

but this fails with:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

error[E0382]: use of moved value: `g`
 --> src/main.rs:7:49
  |
4 | fn some_func(g : Geometry<f64>) {
  |              - move occurs because `g` has type `Geometry`, which does not implement the `Copy` trait
5 |     if let Ok(p) = Point::try_from(g) {
  |                                    - value moved here
6 |         print!("POINT");
7 |     } else if let Ok(ls) = LineString::try_from(g) { 
  |                                                 ^ value used here after move
  |
help: consider cloning the value if the performance cost is acceptable
  |
5 |     if let Ok(p) = Point::try_from(g.clone()) {
  |                                     ++++++++

So I was changing the function to take a geometry refernce:

fn some_func(g : &Geometry<f64>)

but that fails with:

the trait From<&Geometry> is not implemented for geo_types::Point<_>

Next thing I tried is to de-reference the geometry:

Point::try_from(*g)

but this also fails with:

cannot move out of *g which is behind a shared reference
move occurs because *g has type Geometry, which does not implement the Copy trait

So what can I do to get this code working or how can I do this differently?

>Solution :

Note that Geometry is an enum, so you should use pattern matching to check which variant you are using.

pub enum Geometry<T: CoordNum = f64> {
    Point(Point<T>),
    Line(Line<T>),
    LineString(LineString<T>),
    Polygon(Polygon<T>),
    MultiPoint(MultiPoint<T>),
    MultiLineString(MultiLineString<T>),
    MultiPolygon(MultiPolygon<T>),
    GeometryCollection(GeometryCollection<T>),
    Rect(Rect<T>),
    Triangle(Triangle<T>),
}

So you can rewrite your function as follows:

use geo_types::{Geometry, Point, LineString};

fn some_func(g : Geometry<f64>) {

    match g {
        Geometry::Point(_) => print!("POINT"),
        Geometry::LineString(_) => print!("LINESTRING"),
        // It's not really unknown, because there are other enum variants,
        // but I left it to not change your original (intended?) bahavior.
        _ -> print!("UNKNOWN")
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading