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

Latitude & Longitude misplacement of decoding ParsePolygon. #115

Closed
3 tasks done
nomoneynohoney opened this issue Jun 12, 2023 · 5 comments · Fixed by #116 or #118
Closed
3 tasks done

Latitude & Longitude misplacement of decoding ParsePolygon. #115

nomoneynohoney opened this issue Jun 12, 2023 · 5 comments · Fixed by #116 or #118
Labels
bug Something isn't working

Comments

@nomoneynohoney
Copy link

New Issue Checklist

Issue Description

Latitude & Longitude misplacement of decoding ParsePolygon: The order of the element in polygon is [lat, lon], the current decoding order is misplacement. The error is found at ParsePolygon: 108.

Steps to reproduce

Use [[25.1234, 121.4567], [24.321, 121.1234], [22.11, 101.321]] as test polygon data in database. Caused a decoding error.

Actual Outcome

error.

Expected Outcome

a sequence of GeoPoint.

Environment

5.7.0

Client

  • Parse Swift SDK version: 5.7.0
  • Xcode version: 14.3.1
  • Operating system (iOS, macOS, watchOS, etc.): macOS
  • Operating system version: 13.4

Server

  • Parse Server version: 6.2.0
  • Operating system: Ubuntu 20.04 LTS
  • Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): Linode

Database

  • System (MongoDB or Postgres): MongoDB
  • Database version: 6.0.6
  • Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc): Linode

Logs

@cbaker6
Copy link
Member

cbaker6 commented Jun 12, 2023

Can you post the actual error returned from the server.

What happens when you run the Playground code?

//: How to add `ParseBytes` and `ParsePolygon` to objects.
let points = [
try ParseGeoPoint(latitude: 0, longitude: 0),
try ParseGeoPoint(latitude: 0, longitude: 1),
try ParseGeoPoint(latitude: 1, longitude: 1),
try ParseGeoPoint(latitude: 1, longitude: 0),
try ParseGeoPoint(latitude: 0, longitude: 0)
]
do {
let polygon = try ParsePolygon(points)
let bytes = ParseBytes(data: "hello world".data(using: .utf8)!)
var gameData = GameData(bytes: bytes, polygon: polygon)
gameData = try await gameData.save()
print("Successfully saved: \(gameData)")
} catch {
print("Error saving: \(error.localizedDescription)")
}

@nomoneynohoney
Copy link
Author

ParsePolygon.swift, line: 108. the order of a point in the polygon should be [lat, lon].

@nomoneynohoney
Copy link
Author

There won't be error, because the value is decodable. but the order is misplaced, so if u really generate a sequence of coordinates, save into db, then use ParseSwift to decode it and place them back on map. you will find the error.

@cbaker6 cbaker6 added the bug Something isn't working label Jun 12, 2023
@cbaker6 cbaker6 linked a pull request Jun 12, 2023 that will close this issue
4 tasks
@cbaker6 cbaker6 added question Further information is requested and removed bug Something isn't working labels Jun 12, 2023
@cbaker6
Copy link
Member

cbaker6 commented Jun 12, 2023

There won't be error, because the value is decodable. but the order is misplaced, so if u really generate a sequence of coordinates, save into db, then use ParseSwift to decode it and place them back on map. you will find the error.

You stated it caused a decoding error, this is the error I was referring to:

Use [[25.1234, 121.4567], [24.321, 121.1234], [22.11, 101.321]] as test polygon data in database. Caused a decoding error.

My tests show that the current implementation is correct (for Postgres and Mongo). The server needs ParsePolygon coordinates to be encoded as (longitude, latitude), not (latitude, longitude) in order to use ParsePolygon for queries and saved objects. On the other hand, when using ParseGeoPoint's directly, the server needs encoding (latitude, longitude). When you decode ParsePolygon it should always decode properly to latitude and longitude for each ParseGeoPoint. All of this can be seen in parse-community/parse-server#4607 and the server-side tests:

I've updated the Playground examples so you can run them directly to test what I mentioned above:

//: Define initial GameScore.
var score = GameScore(points: 10)
do {
try score.location = ParseGeoPoint(latitude: 40.0, longitude: -30.0)
let points: [ParseGeoPoint] = [
try .init(latitude: 35.0, longitude: -30.0),
try .init(latitude: 42.0, longitude: -35.0),
try .init(latitude: 42.0, longitude: -20.0)
]
score.polygon = try ParsePolygon(points)
}
/*:
Save asynchronously with completion block - performs work on background
queue and returns to specified callbackQueue.
If no callbackQueue is specified it returns to main queue.
*/
score.save { result in
switch result {
case .success(let savedScore):
assert(savedScore.objectId != nil)
assert(savedScore.createdAt != nil)
assert(savedScore.updatedAt != nil)
assert(savedScore.points == 10)
assert(savedScore.location != nil)
assert(savedScore.polygon != nil)
guard let location = savedScore.location else {
print("Something went wrong")
return
}
print("Saved location: \(location)")
guard let polygon = savedScore.polygon else {
print("Something went wrong")
return
}
print("Saved polygon: \(polygon)")
print("Saved polygon geopoints: \(polygon.coordinates)")
case .failure(let error):
assertionFailure("Error saving: \(error)")
}
}

Which results in the following output:

# Postgres
Saved location: {"__type":"GeoPoint","latitude":40,"longitude":-30}
Saved polygon: {"__type":"Polygon","coordinates":[[-30,35],[-35,42],[-20,42]]}
Saved polygon geopoints: [{"__type":"GeoPoint","latitude":35,"longitude":-30}, {"__type":"GeoPoint","latitude":42,"longitude":-35}, {"__type":"GeoPoint","latitude":42,"longitude":-20}]

# Mongo
Saved location: {"__type":"GeoPoint","latitude":40,"longitude":-30}
Saved polygon: {"__type":"Polygon","coordinates":[[-30,35],[-35,42],[-20,42]]}
Saved polygon geopoints: [{"__type":"GeoPoint","latitude":35,"longitude":-30}, {"__type":"GeoPoint","latitude":42,"longitude":-35}, {"__type":"GeoPoint","latitude":42,"longitude":-20}]

The following test was improved to ensure all of the aforementioned is maintained:

func testEncode() throws {
let polygon = try ParsePolygon(points)
let expected = "{\"__type\":\"Polygon\",\"coordinates\":[[0,0],[1,0],[1,1],[0,1],[0,0]]}"
XCTAssertEqual(polygon.debugDescription, expected)
guard polygon.coordinates.count == points.count else {
XCTAssertEqual(polygon.coordinates.count, points.count)
return
}
for (index, coordinates) in polygon.coordinates.enumerated() {
XCTAssertEqual(coordinates, points[index])
}
}

@cbaker6 cbaker6 reopened this Jun 13, 2023
@cbaker6 cbaker6 added bug Something isn't working and removed question Further information is requested labels Jun 13, 2023
@cbaker6
Copy link
Member

cbaker6 commented Jun 13, 2023

It looks like there may be a small bug here as the server handles saved polygons and queried polygons differently. Still investigating...

See #118

@cbaker6 cbaker6 linked a pull request Jun 13, 2023 that will close this issue
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
2 participants