geo中的distance计算
This commit is contained in:
parent
f72a9eb6fe
commit
39eec99c98
|
|
@ -65,10 +65,11 @@ export declare type DeduceFilter<SH extends GeneralEntityShape> = MakeFilter<Att
|
|||
export declare type DeduceSorterAttr<SH extends GeneralEntityShape> = OneOf<{
|
||||
[K: string]: 1 | object | undefined;
|
||||
} & ExprOp<keyof SH>>;
|
||||
export declare type DeduceSorter<SH extends GeneralEntityShape> = Array<{
|
||||
export declare type DeduceSorterItem<SH extends GeneralEntityShape> = {
|
||||
$attr: DeduceSorterAttr<SH>;
|
||||
$direction?: "asc" | "desc";
|
||||
}>;
|
||||
};
|
||||
export declare type DeduceSorter<SH extends GeneralEntityShape> = Array<DeduceSorterItem<SH>>;
|
||||
export declare type DeduceSelection<SH extends GeneralEntityShape> = Selection<DeduceProjection<SH>, DeduceFilter<SH>, DeduceSorter<SH>>;
|
||||
export declare type DeduceCreateOperationData<SH extends GeneralEntityShape> = FormCreateData<SH> & {
|
||||
[k: string]: any;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||
exports.execOp = exports.opMultipleParams = exports.isExpression = exports.isMathExpression = exports.isCompareExpression = exports.isBoolExpression = exports.isLogicExpression = exports.isDateExpression = exports.isGeoExpression = void 0;
|
||||
const assert_1 = __importDefault(require("assert"));
|
||||
const luxon_1 = require("luxon");
|
||||
const geo_1 = require("../utils/geo");
|
||||
;
|
||||
;
|
||||
;
|
||||
|
|
@ -305,9 +306,16 @@ function execOp(op, params, obscure) {
|
|||
}
|
||||
}
|
||||
}
|
||||
case '$contains': {
|
||||
}
|
||||
case '$distance': {
|
||||
const [geo1, geo2] = params;
|
||||
const { type: type1, coordinate: coordinate1 } = geo1;
|
||||
const { type: type2, coordinate: coordinate2 } = geo2;
|
||||
if (type1 !== 'point' || type2 !== 'point') {
|
||||
throw new Error('目前只支持point类型的距离运算');
|
||||
}
|
||||
return (0, geo_1.getDistanceBetweenPoints)(coordinate1[1], coordinate1[0], coordinate2[1], coordinate2[0]);
|
||||
}
|
||||
case '$contains': {
|
||||
}
|
||||
default: {
|
||||
(0, assert_1.default)(false, `不能识别的expression运算符:${op}`);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* 计算地球上两点之间的球面距离
|
||||
*/
|
||||
export declare function getDistanceBetweenPoints(lat1: number, lon1: number, lat2: number, lon2: number): number;
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getDistanceBetweenPoints = void 0;
|
||||
/**
|
||||
* 计算地球上两点之间的球面距离
|
||||
*/
|
||||
function getDistanceBetweenPoints(lat1, lon1, lat2, lon2) {
|
||||
// 转为弧度
|
||||
function toRadians(d) {
|
||||
return d * Math.PI / 180;
|
||||
}
|
||||
const R = 6378137; // 地球长半径
|
||||
const φ1 = toRadians(lat1);
|
||||
const φ2 = toRadians(lat2);
|
||||
const Δφ = toRadians(lat2 - lat1);
|
||||
const Δλ = toRadians(lon2 - lon1);
|
||||
const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
|
||||
Math.cos(φ1) * Math.cos(φ2) *
|
||||
Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
|
||||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
const d = R * c;
|
||||
return d * 1000;
|
||||
}
|
||||
exports.getDistanceBetweenPoints = getDistanceBetweenPoints;
|
||||
|
|
@ -88,10 +88,12 @@ export type DeduceSorterAttr<SH extends GeneralEntityShape> = OneOf<{
|
|||
[K: string]: 1 | object | undefined;
|
||||
} & ExprOp<keyof SH>>;
|
||||
|
||||
export type DeduceSorter<SH extends GeneralEntityShape> = Array<{
|
||||
export type DeduceSorterItem<SH extends GeneralEntityShape> = {
|
||||
$attr: DeduceSorterAttr<SH>;
|
||||
$direction?: "asc" | "desc";
|
||||
}>;
|
||||
};
|
||||
|
||||
export type DeduceSorter<SH extends GeneralEntityShape> = Array<DeduceSorterItem<SH>>;
|
||||
|
||||
export type DeduceSelection<SH extends GeneralEntityShape> = Selection<DeduceProjection<SH>, DeduceFilter<SH>, DeduceSorter<SH>>;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import assert from 'assert';
|
|||
import { RefAttr } from "./Demand";
|
||||
import { Geo } from "./Geo";
|
||||
import { DateTime, Interval } from 'luxon';
|
||||
import { getDistanceBetweenPoints } from '../utils/geo';
|
||||
|
||||
|
||||
export type RefOrExpression<A> = RefAttr<A> | Expression<A>;
|
||||
|
|
@ -409,11 +410,18 @@ export function execOp(op: string, params: any, obscure?: boolean): ExpressionCo
|
|||
}
|
||||
}
|
||||
}
|
||||
case '$distance': {
|
||||
const [geo1, geo2] = params;
|
||||
const { type: type1, coordinate: coordinate1 } = geo1;
|
||||
const { type: type2, coordinate: coordinate2 } = geo2;
|
||||
if (type1 !== 'point' || type2 !== 'point') {
|
||||
throw new Error('目前只支持point类型的距离运算');
|
||||
}
|
||||
|
||||
return getDistanceBetweenPoints(coordinate1[1], coordinate1[0], coordinate2[1], coordinate2[0]);
|
||||
}
|
||||
case '$contains': {
|
||||
|
||||
}
|
||||
case '$distance': {
|
||||
|
||||
}
|
||||
default: {
|
||||
assert(false, `不能识别的expression运算符:${op}`);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* 计算地球上两点之间的球面距离
|
||||
*/
|
||||
export function getDistanceBetweenPoints(lat1: number, lon1: number, lat2: number, lon2: number) {
|
||||
// 转为弧度
|
||||
function toRadians(d: number) {
|
||||
return d * Math.PI / 180;
|
||||
}
|
||||
|
||||
const R = 6378137; // 地球长半径
|
||||
const φ1 = toRadians(lat1);
|
||||
const φ2 = toRadians(lat2);
|
||||
const Δφ = toRadians(lat2 - lat1);
|
||||
const Δλ = toRadians(lon2 - lon1);
|
||||
|
||||
const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
|
||||
Math.cos(φ1) * Math.cos(φ2) *
|
||||
Math.sin(Δλ/2) * Math.sin(Δλ/2);
|
||||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
||||
|
||||
const d = R * c;
|
||||
|
||||
return d * 1000;
|
||||
}
|
||||
Loading…
Reference in New Issue