import * as T from '@turf/turf'
import * as H from '@turf/helpers'
import { extend, notNULL } from '../../util'
import Zondy from '../Zondy'
import ArcGisGeometry from './Geometry'
import ArcGisPoint from './Point'
function initCenter(me) {
const 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])
]
const featureCollection = H.featureCollection(points)
const coordinates = T.center(featureCollection).geometry.coordinates
return new ArcGisPoint({
longitude: coordinates[0],
latitude: coordinates[1]
})
}
/**
* @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 (const 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 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 *= factor
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) {
const cur = this.center
const 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 default ArcGisExtent
Zondy.Service.ArcGisExtent = ArcGisExtent