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

Working with Empty Polygon #206

Open
ElnazTaqizadeh opened this issue Sep 2, 2020 · 4 comments
Open

Working with Empty Polygon #206

ElnazTaqizadeh opened this issue Sep 2, 2020 · 4 comments

Comments

@ElnazTaqizadeh
Copy link

I'm using GEOswift in an engineering plotting app. I need to define and work with empty polygons in different steps. Before the recent release, it was working perfectly fine, but now whenever I have an empty polygon/geometry, it gives me:

Fatal error: Unexpectedly found nil while unwrapping an Optional

Here are some examples I have this issue with:

let poly1 = try! Geometry(wkt: "POLYGON((0 0, 0 0, 0 0, 0 0))")
let poly2 = try! Geometry(wkt: "POLYGON((1 1, 1 1, 1 1, 1 1))")
let poly1_intersect_poly2 = try! poly1.intersection(with: poly2)
let intersect_wkt = try! poly1_intersect_poly2!.wkt()
union_poly = try! (poly3)!.union(with: poly4!)
let union_wkt = try! union_poly!.wkt()

poly1 is an empty polygon so the program crashes when I'm trying to get a union.

What can I change in my code to avoid such crashes?

@macdrevx
Copy link
Member

macdrevx commented Sep 3, 2020

What are the definitions of poly3 and poly4 which are referenced in the lower code block?

@macdrevx
Copy link
Member

macdrevx commented Sep 3, 2020

In testing the first part, I'm seeing that poly1.intersection(with: poly2) returns nil because the two polygons do not intersect. How would you expect to handle that case?

@ElnazTaqizadeh
Copy link
Author

Correct, the output is an empty polygon, and in the logic of my app, it should be fine. Here's a simple example; maybe it clarifies what I need to implement.

Let's say I have two sets:

A = {1, 2, 3}
B = {} (an empty set)

I should be able to apply intersection and get an empty set as a result, right?

A⋂B = {}

It's a similar case in what we have here with this polygon. I want to use the intersection method without the app crashing.
Does it make sense now?

@macdrevx
Copy link
Member

macdrevx commented Sep 4, 2020

Supporting empty geometry is an interesting problem. Note that "POLYGON((0 0, 0 0, 0 0, 0 0))" isn't actually considered an empty polygon in WKT. Instead, there's a symbol EMPTY that indicates a geometry with 0 coordinates.

GEOSwift itself establishes invariants that preclude the possibility of empty Points, LineStrings, and Polygons (via Polygon.LinearRing). These invariants are useful to reduce optionality and edge cases throughout the code.

That said, I can see the argument for modeling empty versions of Point, LineString, and Polygon (and maybe Polygon.LinearRing). I imagine this would be a fairly large project and would likely result in a 8.0 release of this library.

In the meantime, I think you'll need to find a way to handle the possibility of nil as the representation of empty geometry. The specific solution will depend on your use case. For example, if you need to take the intersection of a collection of polygons and the serialize the result to WKT, you could write:

extension Array where Element: GeometryConvertible {
    func intersection() throws -> Geometry? {
        var result = first
        for p in dropFirst() {
            result = try result?.intersection(with: p)
        }
        return result
    }
}

try polygons.intersection()?.wkt() ?? "POLYGON EMPTY"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants