import {extend, Zondy,notNULL} from "../common";
import {ArcGisGeometry} from "./Geometry";
import {ArcGisPoint} from "./Point";
import * as T from '@turf/turf'
import * as H from '@turf/helpers'
/**
* @class module:ArcGis.ArcGisExtent
* @description ArcGisExtent对象
* @author 基础平台-杨琨
* @param options - {Object} 必选项,构造Extent对象参数。
* @param {String} [query.xmin] 可选项,x轴最小坐标。
* @param {String} [query.ymin] 可选项,x轴最大坐标。
* @param {String} [query.ymin] 可选项,y轴最小坐标。
* @param {String} [query.ymax] 可选项,y轴最小坐标。
* @param {String} [query.zmin] 可选项,z轴最小坐标。
* @param {String} [query.zmax] 可选项,z轴最小坐标。
* @param {String} [query.mmin] 可选项,m轴最小坐标。
* @param {String} [query.mmax] 可选项,m轴最小坐标。
*/
class ArcGisExtent extends ArcGisGeometry{
constructor(options) {
super(options);
this.center = undefined;
this.hasM = false;
this.hasZ = false;
this.height = 0;
this.mmax = undefined;
this.mmin = undefined;
this.type = "extent";
this.width = 0;
this.xmax = 0;
this.xmin = 0;
this.ymax = 0;
this.ymin = 0;
this.zmax = undefined;
this.zmin = undefined;
this.extent = this;
//确保私有变量不能被options修改
this.private = ["center","hasM","hasZ","height","width","type","extent"];
for (let key in this.private){
if(notNULL(options[this.private[key]])){
throw new Error("[accessor] cannot assign to read-only property '" + this.private[key] + "' of ArcGisExtent");
}
}
extend(this,options);
//如果z、m有值,hasZ、hasM采薇true
if(this.zmax || this.zmin){
this.hasZ = true;
}
if(this.mmax || this.mmin){
this.hasM = true;
}
//生成bbox
this._extentPolygon = T.polygon([[
[this.xmin, this.ymin],
[this.xmin, this.ymax],
[this.xmax, this.ymax],
[this.ymax, this.ymin],
[this.xmin, this.ymin]
]],{name:"_extentPlygon"});
//生成中心点
this.center = initCenter(this);
//计算width,height
this.width = this.xmax - this.xmin;
this.height = this.ymax - this.ymin;
}
}
function initCenter(me){
let points = [
H.point( [me.xmin, me.ymin]),
H.point( [me.xmin, me.ymax]),
H.point( [me.xmax, me.ymax]),
H.point( [me.ymax, me.ymin]),
H.point( [me.xmin, me.ymin])
];
let featureCollection = H.featureCollection(points);
let coordinates = T.center(featureCollection).geometry.coordinates;
return new ArcGisPoint({
longitude: coordinates[0],
latitude: coordinates[1]
});
}
/**
* @function module:ArcGis.ArcGisExtent.prototype.equals
* @description 比较两个Extent对象是否相等
* @param extent - {ArcGisExtent} 必选项,要比较的ArcGisExtent对象。
* @returns Boolean,对象是否相等
*/
ArcGisExtent.prototype.equals = function (extent){
return this.mmax === extent.mmax &&
this.mmin === extent.mmin &&
this.xmax === extent.xmax &&
this.xmin === extent.xmin &&
this.ymax === extent.ymax &&
this.ymin === extent.ymin &&
this.zmax === extent.zmax &&
this.zmin === extent.zmin;
}
/**
* @function module:ArcGis.ArcGisExtent.prototype.contains
* @description 判断是否包含一个点或者一个ArcGisExtent对象
* @param geometry - {Geometry} 必选项,要比较的ArcGisExtent对象或者ArcGisPoint对象。
* @returns Boolean,是否包含
*/
ArcGisExtent.prototype.contains = function (geometry){
if(geometry.type === "point"){
let point = geometry.toArray();
point = T.point([point[0], point[1]]);
return T.booleanContains(this._extentPolygon,point)
}
if(geometry.type === "extent"){
return T.booleanContains(this._extentPolygon,geometry._extentPolygon)
}
return false;
}
/**
* @function module:ArcGis.ArcGisExtent.prototype.expand
* @description 根据输入的值,扩大或缩小一个ArcGisExtent
* @param factor - {Number} 必选项,放大或缩小系数。
* @returns ArcGisExtent,缩放后的ArcGisExtent
*/
ArcGisExtent.prototype.expand = function (factor){
if(factor instanceof Number){
factor = Math.abs(factor);
this.width = this.width * factor;
this.height = this.height * factor;
this.xmin = this.center.x - this.width / 2;
this.xmax = this.center.x + this.width / 2;
this.ymin = this.center.y - this.height / 2;
this.ymax = this.center.y + this.height / 2;
return this;
}else {
throw new Error("require is not defined");
}
}
/**
* @function module:ArcGis.ArcGisExtent.prototype.intersects
* @description 比较点、多点、线、多边形、extent是否与当前extent相交
* @param geometry - {Geometry} 必选项,要比较的几何对象。
* @returns Boolean,是否相交
*/
ArcGisExtent.prototype.intersects = function (geometry){
if(!geometry.type){
return false;
}
let geom;
if(geometry.type === "polyline"){
geom = H.multiLineString(geometry.paths);
}else if(geometry.type === "point"){
geom = H.point(geometry.toArray());
}else if(geometry.type === "multipoint"){
geom = H.multiPoint(geometry.points);
}else if(geometry.type === "extent"){
geom = geometry._extentPolygon;
}else if(geometry.type === "polygon"){
geom = H.polygon(geometry.rings);
}
return !T.booleanDisjoint(geom,this._extentPolygon);
}
/**
* @function module:ArcGis.ArcGisExtent.prototype.offset
* @description 根据输入的dx, dy, dz值,平移extend
* @param dx - {Number} 必选项,要平移的x值。
* @param dx - {Number} 必选项,要平移的y值。
* @param dx - {Number} 必选项,要平移的z值。
* @returns ArcGisExtent,平移后的ArcGisExtent对象
*/
ArcGisExtent.prototype.offset = function (dx, dy, dz){
this.xmax += dx;
this.xmin += dx;
this.ymax += dy;
this.ymin += dy;
if(this.hasZ){
this.zmax += dz;
this.zmin += dz;
}else {
this.hasZ = true;
this.zmax = 0;
this.zmin = 0;
}
return this;
}
/**
* @function module:ArcGis.ArcGisExtent.prototype.centerAt
* @description 根据输入的ArcGisPoint对象,生成衣蛾新的中心点
* @param point - {ArcGisPoint} 必选项,新的中心点。
* @returns ArcGisExtent
*/
ArcGisExtent.prototype.centerAt = function (point){
if(point instanceof ArcGisPoint){
this.center = new ArcGisPoint({
longitude: point.x,
latitude: point.y
});
this.xmin = this.center.x - this.width / 2;
this.xmax = this.center.x + this.width / 2;
this.ymin = this.center.y - this.height / 2;
this.ymax = this.center.y + this.height / 2;
return this;
}
}
ArcGisExtent.prototype.normalize = function (){
return [this];
}
/**
* @function module:ArcGis.ArcGisExtent.prototype.union
* @description 输入一个ArcGisExtent对象,与原extent对象合并,生成一个新的extent
* @param extent - {ArcGisExtent} 必选项,要合并的ArcGisExtent对象。
* @returns ArcGisExtent,新的Extent对象
*/
ArcGisExtent.prototype.union = function (extent){
let cur = this.center;
let nex = extent.center;
if(((nex.x - cur.x) > 0 && (nex.y - cur.y) > 0) || ((nex.x - cur.x) === 0 && (nex.y - cur.y) > 0)
|| ((nex.x - cur.x) === 0 && (nex.y - cur.y) === 0)
|| ((nex.x - cur.x) > 0 && (nex.y - cur.y) === 0)){
this.xmax = extent.xmax;
this.ymax = extent.ymax;
}else if((nex.x - cur.x) > 0 && (nex.y - cur.y) < 0 || ((nex.x - cur.x) === 0 && (nex.y - cur.y) < 0)){
this.xmax = extent.xmax;
this.ymin = extent.ymin;
}else if((nex.x - cur.x) < 0 && (nex.y - cur.y) < 0){
this.xmin = extent.xmin;
this.ymin = extent.ymin;
}else if((nex.x - cur.x) < 0 && (nex.y - cur.y || ((nex.x - cur.x) < 0 && (nex.y - cur.y) < 0)) === 0){
this.xmin = extent.xmin;
this.ymax = extent.ymax;
}
this.center = initCenter(this);
//计算width,height
this.width = this.xmax - this.xmin;
this.height = this.ymax - this.ymin;
return this;
}
/**
* @function module:ArcGis.ArcGisExtent.prototype.toString
* @description 返回如下格式的字符串:"xmin,ymin,xmax,ymax"
* @returns Sting
*/
ArcGisExtent.prototype.toString = function (){
return this.xmin + "," + this.ymin + "," + this.xmax + "," + this.ymax;
}
export {ArcGisExtent};
Zondy.Service.ArcGisExtent = ArcGisExtent;