goog.provide('ol.geom.Polygon'); goog.require('goog.array'); goog.require('goog.asserts'); goog.require('ol.extent'); goog.require('ol.geom.GeometryType'); goog.require('ol.geom.LinearRing'); goog.require('ol.geom.Point'); goog.require('ol.geom.SimpleGeometry'); goog.require('ol.geom.flat'); goog.require('ol.geom.flat.closest'); goog.require('ol.geom.simplify'); /** * @constructor * @extends {ol.geom.SimpleGeometry} * @param {ol.geom.RawPolygon} coordinates Coordinates. * @param {ol.geom.GeometryLayout=} opt_layout Layout. * @todo stability experimental */ ol.geom.Polygon = function(coordinates, opt_layout) { goog.base(this); /** * @type {Array.} * @private */ this.ends_ = []; /** * @private * @type {number} */ this.flatInteriorPointRevision_ = -1; /** * @private * @type {ol.Coordinate} */ this.flatInteriorPoint_ = null; /** * @private * @type {number} */ this.maxDelta_ = -1; /** * @private * @type {number} */ this.maxDeltaRevision_ = -1; /** * @private * @type {number} */ this.orientedRevision_ = -1; /** * @private * @type {Array.} */ this.orientedFlatCoordinates_ = null; this.setCoordinates(coordinates, opt_layout); }; goog.inherits(ol.geom.Polygon, ol.geom.SimpleGeometry); /** * @param {ol.geom.LinearRing} linearRing Linear ring. */ ol.geom.Polygon.prototype.appendLinearRing = function(linearRing) { goog.asserts.assert(linearRing.getLayout() == this.layout); if (goog.isNull(this.flatCoordinates)) { this.flatCoordinates = linearRing.getFlatCoordinates().slice(); } else { goog.array.extend(this.flatCoordinates, linearRing.getFlatCoordinates()); } this.ends_.push(this.flatCoordinates.length); this.dispatchChangeEvent(); }; /** * @inheritDoc */ ol.geom.Polygon.prototype.clone = function() { var polygon = new ol.geom.Polygon(null); polygon.setFlatCoordinates( this.layout, this.flatCoordinates.slice(), this.ends_.slice()); return polygon; }; /** * @inheritDoc */ ol.geom.Polygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) { if (minSquaredDistance < ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) { return minSquaredDistance; } if (this.maxDeltaRevision_ != this.getRevision()) { this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getsMaxSquaredDelta( this.flatCoordinates, 0, this.ends_, this.stride, 0)); this.maxDeltaRevision_ = this.getRevision(); } return ol.geom.flat.closest.getsClosestPoint( this.flatCoordinates, 0, this.ends_, this.stride, this.maxDelta_, true, x, y, closestPoint, minSquaredDistance); }; /** * @inheritDoc */ ol.geom.Polygon.prototype.containsXY = function(x, y) { return ol.geom.flat.linearRingsContainsXY( this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, x, y); }; /** * @return {number} Area. * @todo stability experimental */ ol.geom.Polygon.prototype.getArea = function() { return ol.geom.flat.linearRingsArea( this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride); }; /** * @return {ol.geom.RawPolygon} Coordinates. * @todo stability experimental */ ol.geom.Polygon.prototype.getCoordinates = function() { return ol.geom.flat.inflateCoordinatess( this.flatCoordinates, 0, this.ends_, this.stride); }; /** * @return {Array.} Ends. */ ol.geom.Polygon.prototype.getEnds = function() { return this.ends_; }; /** * @return {Array.} Interior point. */ ol.geom.Polygon.prototype.getFlatInteriorPoint = function() { if (this.flatInteriorPointRevision_ != this.getRevision()) { var flatCenter = ol.extent.getCenter(this.getExtent()); this.flatInteriorPoint_ = ol.geom.flat.linearRingsGetInteriorPoint( this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, flatCenter, 0); this.flatInteriorPointRevision_ = this.getRevision(); } return this.flatInteriorPoint_; }; /** * @return {ol.geom.Point} Interior point. */ ol.geom.Polygon.prototype.getInteriorPoint = function() { return new ol.geom.Point(this.getFlatInteriorPoint()); }; /** * @param {number} index Index. * @return {ol.geom.LinearRing} Linear ring. */ ol.geom.Polygon.prototype.getLinearRing = function(index) { goog.asserts.assert(0 <= index && index < this.ends_.length); if (index < 0 || this.ends_.length <= index) { return null; } var linearRing = new ol.geom.LinearRing(null); linearRing.setFlatCoordinates(this.layout, this.flatCoordinates.slice( index === 0 ? 0 : this.ends_[index - 1], this.ends_[index])); return linearRing; }; /** * @return {Array.} Linear rings. * @todo stability experimental */ ol.geom.Polygon.prototype.getLinearRings = function() { var layout = this.layout; var flatCoordinates = this.flatCoordinates; var ends = this.ends_; var linearRings = []; var offset = 0; var i, ii; for (i = 0, ii = ends.length; i < ii; ++i) { var end = ends[i]; var linearRing = new ol.geom.LinearRing(null); linearRing.setFlatCoordinates(layout, flatCoordinates.slice(offset, end)); linearRings.push(linearRing); offset = end; } return linearRings; }; /** * @return {Array.} Oriented flat coordinates. */ ol.geom.Polygon.prototype.getOrientedFlatCoordinates = function() { if (this.orientedRevision_ != this.getRevision()) { var flatCoordinates = this.flatCoordinates; if (ol.geom.flat.linearRingsAreOriented( flatCoordinates, 0, this.ends_, this.stride)) { this.orientedFlatCoordinates_ = flatCoordinates; } else { this.orientedFlatCoordinates_ = flatCoordinates.slice(); this.orientedFlatCoordinates_.length = ol.geom.flat.orientLinearRings( this.orientedFlatCoordinates_, 0, this.ends_, this.stride); } this.orientedRevision_ = this.getRevision(); } return this.orientedFlatCoordinates_; }; /** * @inheritDoc */ ol.geom.Polygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) { var simplifiedFlatCoordinates = []; var simplifiedEnds = []; simplifiedFlatCoordinates.length = ol.geom.simplify.quantizes( this.flatCoordinates, 0, this.ends_, this.stride, Math.sqrt(squaredTolerance), simplifiedFlatCoordinates, 0, simplifiedEnds); var simplifiedPolygon = new ol.geom.Polygon(null); simplifiedPolygon.setFlatCoordinates( ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEnds); return simplifiedPolygon; }; /** * @inheritDoc */ ol.geom.Polygon.prototype.getType = function() { return ol.geom.GeometryType.POLYGON; }; /** * @param {ol.geom.RawPolygon} coordinates Coordinates. * @param {ol.geom.GeometryLayout=} opt_layout Layout. * @todo stability experimental */ ol.geom.Polygon.prototype.setCoordinates = function(coordinates, opt_layout) { if (goog.isNull(coordinates)) { this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.ends_); } else { this.setLayout(opt_layout, coordinates, 2); if (goog.isNull(this.flatCoordinates)) { this.flatCoordinates = []; } var ends = ol.geom.flat.deflateCoordinatess( this.flatCoordinates, 0, coordinates, this.stride, this.ends_); this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1]; this.dispatchChangeEvent(); } }; /** * @param {ol.geom.GeometryLayout} layout Layout. * @param {Array.} flatCoordinates Flat coordinates. * @param {Array.} ends Ends. */ ol.geom.Polygon.prototype.setFlatCoordinates = function(layout, flatCoordinates, ends) { if (goog.isNull(flatCoordinates)) { goog.asserts.assert(!goog.isNull(ends) && ends.length === 0); } else if (ends.length === 0) { goog.asserts.assert(flatCoordinates.length === 0); } else { goog.asserts.assert(flatCoordinates.length == ends[ends.length - 1]); } this.setFlatCoordinatesInternal(layout, flatCoordinates); this.ends_ = ends; this.dispatchChangeEvent(); };