| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- import Area from '../algorithm/Area'
- import Geometry from './Geometry'
- import Arrays from '../../../../java/util/Arrays'
- import CoordinateFilter from './CoordinateFilter'
- import hasInterface from '../../../../hasInterface'
- import IllegalArgumentException from '../../../../java/lang/IllegalArgumentException'
- import Orientation from '../algorithm/Orientation'
- import CoordinateSequences from './CoordinateSequences'
- import GeometryComponentFilter from './GeometryComponentFilter'
- import Polygonal from './Polygonal'
- import GeometryFilter from './GeometryFilter'
- import CoordinateSequenceFilter from './CoordinateSequenceFilter'
- export default class Polygon extends Geometry {
- constructor() {
- super()
- Polygon.constructor_.apply(this, arguments)
- }
- static constructor_() {
- this._shell = null
- this._holes = null
- let shell = arguments[0], holes = arguments[1], factory = arguments[2]
- Geometry.constructor_.call(this, factory)
- if (shell === null)
- shell = this.getFactory().createLinearRing()
-
- if (holes === null)
- holes = []
-
- if (Geometry.hasNullElements(holes))
- throw new IllegalArgumentException('holes must not contain null elements')
-
- if (shell.isEmpty() && Geometry.hasNonEmptyElements(holes))
- throw new IllegalArgumentException('shell is empty but holes are not')
-
- this._shell = shell
- this._holes = holes
- }
- computeEnvelopeInternal() {
- return this._shell.getEnvelopeInternal()
- }
- getCoordinates() {
- if (this.isEmpty())
- return []
-
- const coordinates = new Array(this.getNumPoints()).fill(null)
- let k = -1
- const shellCoordinates = this._shell.getCoordinates()
- for (let x = 0; x < shellCoordinates.length; x++) {
- k++
- coordinates[k] = shellCoordinates[x]
- }
- for (let i = 0; i < this._holes.length; i++) {
- const childCoordinates = this._holes[i].getCoordinates()
- for (let j = 0; j < childCoordinates.length; j++) {
- k++
- coordinates[k] = childCoordinates[j]
- }
- }
- return coordinates
- }
- getArea() {
- let area = 0.0
- area += Area.ofRing(this._shell.getCoordinateSequence())
- for (let i = 0; i < this._holes.length; i++)
- area -= Area.ofRing(this._holes[i].getCoordinateSequence())
-
- return area
- }
- copyInternal() {
- const shellCopy = this._shell.copy()
- const holeCopies = new Array(this._holes.length).fill(null)
- for (let i = 0; i < this._holes.length; i++)
- holeCopies[i] = this._holes[i].copy()
-
- return new Polygon(shellCopy, holeCopies, this._factory)
- }
- isRectangle() {
- if (this.getNumInteriorRing() !== 0) return false
- if (this._shell === null) return false
- if (this._shell.getNumPoints() !== 5) return false
- const seq = this._shell.getCoordinateSequence()
- const env = this.getEnvelopeInternal()
- for (let i = 0; i < 5; i++) {
- const x = seq.getX(i)
- if (!(x === env.getMinX() || x === env.getMaxX())) return false
- const y = seq.getY(i)
- if (!(y === env.getMinY() || y === env.getMaxY())) return false
- }
- let prevX = seq.getX(0)
- let prevY = seq.getY(0)
- for (let i = 1; i <= 4; i++) {
- const x = seq.getX(i)
- const y = seq.getY(i)
- const xChanged = x !== prevX
- const yChanged = y !== prevY
- if (xChanged === yChanged) return false
- prevX = x
- prevY = y
- }
- return true
- }
- equalsExact() {
- if (arguments.length === 2 && (typeof arguments[1] === 'number' && arguments[0] instanceof Geometry)) {
- const other = arguments[0], tolerance = arguments[1]
- if (!this.isEquivalentClass(other))
- return false
-
- const otherPolygon = other
- const thisShell = this._shell
- const otherPolygonShell = otherPolygon._shell
- if (!thisShell.equalsExact(otherPolygonShell, tolerance))
- return false
-
- if (this._holes.length !== otherPolygon._holes.length)
- return false
-
- for (let i = 0; i < this._holes.length; i++)
- if (!this._holes[i].equalsExact(otherPolygon._holes[i], tolerance))
- return false
-
-
- return true
- } else {
- return super.equalsExact.apply(this, arguments)
- }
- }
- normalize() {
- if (arguments.length === 0) {
- this._shell = this.normalized(this._shell, true)
- for (let i = 0; i < this._holes.length; i++)
- this._holes[i] = this.normalized(this._holes[i], false)
-
- Arrays.sort(this._holes)
- } else if (arguments.length === 2) {
- const ring = arguments[0], clockwise = arguments[1]
- if (ring.isEmpty())
- return null
-
- const seq = ring.getCoordinateSequence()
- const minCoordinateIndex = CoordinateSequences.minCoordinateIndex(seq, 0, seq.size() - 2)
- CoordinateSequences.scroll(seq, minCoordinateIndex, true)
- if (Orientation.isCCW(seq) === clockwise) CoordinateSequences.reverse(seq)
- }
- }
- getCoordinate() {
- return this._shell.getCoordinate()
- }
- getNumInteriorRing() {
- return this._holes.length
- }
- getBoundaryDimension() {
- return 1
- }
- reverseInternal() {
- const shell = this.getExteriorRing().reverse()
- const holes = new Array(this.getNumInteriorRing()).fill(null)
- for (let i = 0; i < holes.length; i++)
- holes[i] = this.getInteriorRingN(i).reverse()
-
- return this.getFactory().createPolygon(shell, holes)
- }
- getTypeCode() {
- return Geometry.TYPECODE_POLYGON
- }
- getDimension() {
- return 2
- }
- getLength() {
- let len = 0.0
- len += this._shell.getLength()
- for (let i = 0; i < this._holes.length; i++)
- len += this._holes[i].getLength()
-
- return len
- }
- getNumPoints() {
- let numPoints = this._shell.getNumPoints()
- for (let i = 0; i < this._holes.length; i++)
- numPoints += this._holes[i].getNumPoints()
-
- return numPoints
- }
- convexHull() {
- return this.getExteriorRing().convexHull()
- }
- normalized(ring, clockwise) {
- const res = ring.copy()
- this.normalize(res, clockwise)
- return res
- }
- compareToSameClass() {
- if (arguments.length === 1) {
- const o = arguments[0]
- const thisShell = this._shell
- const otherShell = o._shell
- return thisShell.compareToSameClass(otherShell)
- } else if (arguments.length === 2) {
- const o = arguments[0], comp = arguments[1]
- const poly = o
- const thisShell = this._shell
- const otherShell = poly._shell
- const shellComp = thisShell.compareToSameClass(otherShell, comp)
- if (shellComp !== 0) return shellComp
- const nHole1 = this.getNumInteriorRing()
- const nHole2 = poly.getNumInteriorRing()
- let i = 0
- while (i < nHole1 && i < nHole2) {
- const thisHole = this.getInteriorRingN(i)
- const otherHole = poly.getInteriorRingN(i)
- const holeComp = thisHole.compareToSameClass(otherHole, comp)
- if (holeComp !== 0) return holeComp
- i++
- }
- if (i < nHole1) return 1
- if (i < nHole2) return -1
- return 0
- }
- }
- apply() {
- if (hasInterface(arguments[0], CoordinateFilter)) {
- const filter = arguments[0]
- this._shell.apply(filter)
- for (let i = 0; i < this._holes.length; i++)
- this._holes[i].apply(filter)
-
- } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) {
- const filter = arguments[0]
- this._shell.apply(filter)
- if (!filter.isDone())
- for (let i = 0; i < this._holes.length; i++) {
- this._holes[i].apply(filter)
- if (filter.isDone()) break
- }
-
- if (filter.isGeometryChanged()) this.geometryChanged()
- } else if (hasInterface(arguments[0], GeometryFilter)) {
- const filter = arguments[0]
- filter.filter(this)
- } else if (hasInterface(arguments[0], GeometryComponentFilter)) {
- const filter = arguments[0]
- filter.filter(this)
- this._shell.apply(filter)
- for (let i = 0; i < this._holes.length; i++)
- this._holes[i].apply(filter)
-
- }
- }
- getBoundary() {
- if (this.isEmpty())
- return this.getFactory().createMultiLineString()
-
- const rings = new Array(this._holes.length + 1).fill(null)
- rings[0] = this._shell
- for (let i = 0; i < this._holes.length; i++)
- rings[i + 1] = this._holes[i]
-
- if (rings.length <= 1) return this.getFactory().createLinearRing(rings[0].getCoordinateSequence())
- return this.getFactory().createMultiLineString(rings)
- }
- getGeometryType() {
- return Geometry.TYPENAME_POLYGON
- }
- getExteriorRing() {
- return this._shell
- }
- isEmpty() {
- return this._shell.isEmpty()
- }
- getInteriorRingN(n) {
- return this._holes[n]
- }
- get interfaces_() {
- return [Polygonal]
- }
- }
|