text: module.exports = function(gdal) {
  
  	/**
  	 * A 2D bounding box. For 3D envelopes, see {{#crossLink "gdal.Envelope3D"}}gdal.Envelope3D{{/crossLink}}.
  	 *
  	 * (Pure-javascript implementation of [OGREnvelope](http://www.gdal.org/classOGREnvelope.html))
  	 *
  	 * @constructor
  	 * @class gdal.Envelope
  	 * @param {Object} [bounds] An object containing `minX`, `maxX`, `minY`, and `maxY` values.
  	 */
  	var Envelope = function Envelope(envelope) {
  		if (envelope) {
  			this.minX = envelope.minX;
  			this.minY = envelope.minY;
  			this.maxX = envelope.maxX;
  			this.maxY = envelope.maxY;
  		} else {
  			this.minX = 0;
  			this.minY = 0;
  			this.maxX = 0;
  			this.maxY = 0;
  		}
  	};
  
  	/**
  	 * Determines if the envelope has not been set yet.
  	 *
  	 * @method isEmpty
  	 * @return {Boolean}
  	 */
  	Envelope.prototype.isEmpty = function() {
  		return !(this.minX || this.minY || this.maxX || this.maxY);
  	};
  
  	/**
  	 * Unions the provided envelope with the current envelope.
  	 *
  	 * @method merge
  	 * @param {gdal.Envelope} envelope
  	 * @return {void}
  	 */
  	Envelope.prototype.merge = function(envelope) {
  	 	if (arguments.length == 1) {
  			if (this.isEmpty()) {
  				this.minX = envelope.minX;
  				this.maxX = envelope.maxX;
  				this.minY = envelope.minY;
  				this.maxY = envelope.maxY;
  			} else {
  				this.minX = Math.min(envelope.minX, this.minX);
  				this.maxX = Math.max(envelope.maxX, this.maxX);
  				this.minY = Math.min(envelope.minY, this.minY);
  				this.maxY = Math.max(envelope.maxY, this.maxY);
  			}
  		} else {
  			var x = arguments[0];
  			var y = arguments[1];
  			if (this.isEmpty()) {
  				this.minX = this.maxX = x;
  				this.minY = this.maxY = y;
  			} else {
  				this.minX = Math.min(x, this.minX);
  				this.maxX = Math.max(x, this.maxX);
  				this.minY = Math.min(y, this.minY);
  				this.maxY = Math.max(y, this.maxY);
  			}
  		}
  	};
  
  	/**
  	 * Determines if the provided envelope touches it.
  	 *
  	 * @method intersects
  	 * @param {gdal.Envelope} envelope
  	 * @return {Boolean}
  	 */
  	Envelope.prototype.intersects = function(envelope) {
  		return this.minX <= envelope.maxX && this.maxX >= envelope.minX &&
  		       this.minY <= envelope.maxY && this.maxY >= envelope.minY;
  	};
  
  	/**
  	 * Updates the envelope to the intersection of the two envelopes.
  	 *
  	 * @method intersect
  	 * @param {gdal.Envelope} envelope
  	 * @return {void}
  	 */
  	Envelope.prototype.intersect = function(envelope) {
  		if (this.intersects(envelope)) {
  			if (this.isEmpty()) {
  				this.minX = envelope.minX;
  				this.maxX = envelope.maxX;
  				this.minY = envelope.minY;
  				this.maxY = envelope.maxY;
  			} else {
  				this.minX = Math.max(envelope.minX, this.minX);
  				this.maxX = Math.min(envelope.maxX, this.maxX);
  				this.minY = Math.max(envelope.minY, this.minY);
  				this.maxY = Math.min(envelope.maxY, this.maxY);
  			}
  		} else {
  			this.minX = this.maxX = this.minY = this.maxY = 0;
  		}
  	};
  
  	/**
  	 * Determines if the provided envelope is wholly-contained by the current envelope.
  	 *
  	 * @method contains
  	 * @param {gdal.Envelope} envelope
  	 * @return {Boolean}
  	 */
  	Envelope.prototype.contains = function(envelope) {
  		return this.minX <= envelope.minX && this.minY <= envelope.minY &&
  		       this.maxX >= envelope.maxX && this.maxY >= envelope.maxY;
  	};
  
  	/**
  	 * Converts the envelope to a polygon.
  	 *
  	 * @method toPolygon
  	 * @return {gdal.Polygon}
  	 */
  	Envelope.prototype.toPolygon = function() {
  		var polygon = new gdal.Polygon();
  		var ring    = new gdal.LinearRing();
  		ring.points.add(this.minX, this.minY);
  		ring.points.add(this.maxX, this.minY);
  		ring.points.add(this.maxX, this.maxY);
  		ring.points.add(this.minX, this.maxY);
  		ring.points.add(this.minX, this.minY);
  		polygon.rings.add(ring);
  		return polygon;
  	};
  
  	return Envelope;
  
  };