Mongo: Fix reversing polygon coordinates (#4609)
* Fix reversing polygon coordinates * comments fix * real data test * improved tests
This commit is contained in:
@@ -63,12 +63,29 @@ describe('parseObjectToMongoObjectForCreate', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('plain', (done) => {
|
it('parse geopoint to mongo', (done) => {
|
||||||
const geoPoint = {__type: 'GeoPoint', longitude: 180, latitude: -180};
|
const lat = -45;
|
||||||
|
const lng = 45;
|
||||||
|
const geoPoint = {__type: 'GeoPoint', latitude: lat, longitude: lng};
|
||||||
const out = transform.parseObjectToMongoObjectForCreate(null, {location: geoPoint},{
|
const out = transform.parseObjectToMongoObjectForCreate(null, {location: geoPoint},{
|
||||||
fields: {location: {type: 'GeoPoint'}}
|
fields: {location: {type: 'GeoPoint'}}
|
||||||
});
|
});
|
||||||
expect(out.location).toEqual([180, -180]);
|
expect(out.location).toEqual([lng, lat]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parse polygon to mongo', (done) => {
|
||||||
|
const lat1 = -45;
|
||||||
|
const lng1 = 45;
|
||||||
|
const lat2 = -55;
|
||||||
|
const lng2 = 55;
|
||||||
|
const lat3 = -65;
|
||||||
|
const lng3 = 65;
|
||||||
|
const polygon = {__type: 'Polygon', coordinates: [[lat1, lng1],[lat2, lng2],[lat3, lng3]]}
|
||||||
|
const out = transform.parseObjectToMongoObjectForCreate(null, {location: polygon},{
|
||||||
|
fields: {location: {type: 'Polygon'}}
|
||||||
|
});
|
||||||
|
expect(out.location.coordinates).toEqual([[[lng1, lat1],[lng2, lat2],[lng3, lat3],[lng1, lat1]]]);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -144,26 +161,31 @@ describe('parseObjectToMongoObjectForCreate', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('geopoint', (done) => {
|
it('mongo geopoint to parse', (done) => {
|
||||||
const input = {location: [45, -45]};
|
const lat = -45;
|
||||||
|
const lng = 45;
|
||||||
|
const input = {location: [lng, lat]};
|
||||||
const output = transform.mongoObjectToParseObject(null, input, {
|
const output = transform.mongoObjectToParseObject(null, input, {
|
||||||
fields: { location: { type: 'GeoPoint' }},
|
fields: { location: { type: 'GeoPoint' }},
|
||||||
});
|
});
|
||||||
expect(typeof output.location).toEqual('object');
|
expect(typeof output.location).toEqual('object');
|
||||||
expect(output.location).toEqual(
|
expect(output.location).toEqual(
|
||||||
{__type: 'GeoPoint', longitude: 45, latitude: -45}
|
{__type: 'GeoPoint', latitude: lat, longitude: lng}
|
||||||
);
|
);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('polygon', (done) => {
|
it('mongo polygon to parse', (done) => {
|
||||||
const input = {location: { type: 'Polygon', coordinates: [[[45, -45],[45, -45]]]}};
|
const lat = -45;
|
||||||
|
const lng = 45;
|
||||||
|
// Mongo stores polygon in WGS84 lng/lat
|
||||||
|
const input = {location: { type: 'Polygon', coordinates: [[[lat, lng],[lat, lng]]]}};
|
||||||
const output = transform.mongoObjectToParseObject(null, input, {
|
const output = transform.mongoObjectToParseObject(null, input, {
|
||||||
fields: { location: { type: 'Polygon' }},
|
fields: { location: { type: 'Polygon' }},
|
||||||
});
|
});
|
||||||
expect(typeof output.location).toEqual('object');
|
expect(typeof output.location).toEqual('object');
|
||||||
expect(output.location).toEqual(
|
expect(output.location).toEqual(
|
||||||
{__type: 'Polygon', coordinates: [[45, -45],[45, -45]]}
|
{__type: 'Polygon', coordinates: [[lng, lat],[lng, lat]]}
|
||||||
);
|
);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -160,6 +160,64 @@ describe('Parse.Polygon testing', () => {
|
|||||||
}, done.fail);
|
}, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('polygonContain query no reverse input (Regression test for #4608)', (done) => {
|
||||||
|
const points1 = [[.25,0],[.25,1.25],[.75,1.25],[.75,0]];
|
||||||
|
const points2 = [[0,0],[0,2],[2,2],[2,0]];
|
||||||
|
const points3 = [[10,10],[10,15],[15,15],[15,10],[10,10]];
|
||||||
|
const polygon1 = new Parse.Polygon(points1);
|
||||||
|
const polygon2 = new Parse.Polygon(points2);
|
||||||
|
const polygon3 = new Parse.Polygon(points3);
|
||||||
|
const obj1 = new TestObject({location: polygon1});
|
||||||
|
const obj2 = new TestObject({location: polygon2});
|
||||||
|
const obj3 = new TestObject({location: polygon3});
|
||||||
|
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
||||||
|
const where = {
|
||||||
|
location: {
|
||||||
|
$geoIntersects: {
|
||||||
|
$point: { __type: 'GeoPoint', latitude: 0.5, longitude:1.0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return rp.post({
|
||||||
|
url: Parse.serverURL + '/classes/TestObject',
|
||||||
|
json: { where, '_method': 'GET' },
|
||||||
|
headers: {
|
||||||
|
'X-Parse-Application-Id': Parse.applicationId,
|
||||||
|
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then((resp) => {
|
||||||
|
expect(resp.results.length).toBe(2);
|
||||||
|
done();
|
||||||
|
}, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('polygonContain query real data (Regression test for #4608)', (done) => {
|
||||||
|
const detroit = [[42.631655189280224,-83.78406753121705],[42.633047793854814,-83.75333640366955],[42.61625254348911,-83.75149921669944],[42.61526926650296,-83.78161794858735],[42.631655189280224,-83.78406753121705]];
|
||||||
|
const polygon = new Parse.Polygon(detroit);
|
||||||
|
const obj = new TestObject({location: polygon});
|
||||||
|
obj.save().then(() => {
|
||||||
|
const where = {
|
||||||
|
location: {
|
||||||
|
$geoIntersects: {
|
||||||
|
$point: { __type: 'GeoPoint', latitude: 42.624599, longitude:-83.770162 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return rp.post({
|
||||||
|
url: Parse.serverURL + '/classes/TestObject',
|
||||||
|
json: { where, '_method': 'GET' },
|
||||||
|
headers: {
|
||||||
|
'X-Parse-Application-Id': Parse.applicationId,
|
||||||
|
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then((resp) => {
|
||||||
|
expect(resp.results.length).toBe(1);
|
||||||
|
done();
|
||||||
|
}, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
it('polygonContain invalid input', (done) => {
|
it('polygonContain invalid input', (done) => {
|
||||||
const points = [[0,0],[0,1],[1,1],[1,0]];
|
const points = [[0,0],[0,1],[1,1],[1,0]];
|
||||||
const polygon = new Parse.Polygon(points);
|
const polygon = new Parse.Polygon(points);
|
||||||
@@ -255,6 +313,24 @@ describe_only_db('mongo')('Parse.Polygon testing', () => {
|
|||||||
}, done.fail);
|
}, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('polygon coordinates reverse input', (done) => {
|
||||||
|
const Config = require('../src/Config');
|
||||||
|
const config = Config.get('test');
|
||||||
|
|
||||||
|
// When stored the first point should be the last point
|
||||||
|
const input = [[12,11],[14,13],[16,15],[18,17]];
|
||||||
|
const output = [[[11,12],[13,14],[15,16],[17,18],[11,12]]];
|
||||||
|
const obj = new TestObject();
|
||||||
|
obj.set('polygon', new Parse.Polygon(input));
|
||||||
|
obj.save().then(() => {
|
||||||
|
return config.database.adapter._rawFind('TestObject', {_id: obj.id});
|
||||||
|
}).then((results) => {
|
||||||
|
expect(results.length).toBe(1);
|
||||||
|
expect(results[0].polygon.coordinates).toEqual(output);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('polygon loop is not valid', (done) => {
|
it('polygon loop is not valid', (done) => {
|
||||||
const coords = [[0,0],[0,1],[1,0],[1,1]];
|
const coords = [[0,0],[0,1],[1,0],[1,1]];
|
||||||
const obj = new TestObject();
|
const obj = new TestObject();
|
||||||
|
|||||||
@@ -1261,9 +1261,13 @@ var GeoPointCoder = {
|
|||||||
|
|
||||||
var PolygonCoder = {
|
var PolygonCoder = {
|
||||||
databaseToJSON(object) {
|
databaseToJSON(object) {
|
||||||
|
// Convert lng/lat -> lat/lng
|
||||||
|
const coords = object.coordinates[0].map((coord) => {
|
||||||
|
return [coord[1], coord[0]];
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
__type: 'Polygon',
|
__type: 'Polygon',
|
||||||
coordinates: object['coordinates'][0]
|
coordinates: coords
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1283,7 +1287,8 @@ var PolygonCoder = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
JSONToDatabase(json) {
|
JSONToDatabase(json) {
|
||||||
const coords = json.coordinates;
|
let coords = json.coordinates;
|
||||||
|
// Add first point to the end to close polygon
|
||||||
if (coords[0][0] !== coords[coords.length - 1][0] ||
|
if (coords[0][0] !== coords[coords.length - 1][0] ||
|
||||||
coords[0][1] !== coords[coords.length - 1][1]) {
|
coords[0][1] !== coords[coords.length - 1][1]) {
|
||||||
coords.push(coords[0]);
|
coords.push(coords[0]);
|
||||||
@@ -1306,6 +1311,10 @@ var PolygonCoder = {
|
|||||||
'GeoJSON: Loop must have at least 3 different vertices'
|
'GeoJSON: Loop must have at least 3 different vertices'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// Convert lat/long -> long/lat
|
||||||
|
coords = coords.map((coord) => {
|
||||||
|
return [coord[1], coord[0]];
|
||||||
|
});
|
||||||
return { type: 'Polygon', coordinates: [coords] };
|
return { type: 'Polygon', coordinates: [coords] };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user