function GePlacemarkManager(ge, camera) {
	var me = this;
	me.ge_ = ge;
	me.camera_ = camera;

	me.viewportNorthBound_ = 0.0;
	me.viewportSouthBound_ = 0.0;
	me.viewportEastBound_ = 0.0;
	me.viewportWestBound_ = 0.0;

	me.outsideNorthBound_ = 0.0;
	me.outsideSouthBound_ = 0.0;
	me.outsideEastBound_ = 0.0;
	me.outsideWestBound_ = 0.0;
	
	me.allPoints_ = [];

	me.gridPoints_ = [];
	me.outsideGridPoints_ = [];
	me.leftoverPoints_ = [];
	
	me.placemarksInView_ = [];
	for(var i=0; i<GePlacemarkManager.NUMBER_COLS_; i++) {
		me.placemarksInView_[i] = [];
	}
	
	this.setATimeout_ = function() {
		// setTimeout(me.updatePoints_(), 10000);
		me.onMapMoveEnd_();
	};
	
	google.earth.addEventListener(ge.getView(), 'viewchangeend', this.setATimeout_);
}

//Static constants:
GePlacemarkManager.NUMBER_COLS_ = 5;
GePlacemarkManager.OUTSIDE_BOUNDS_ = 5;

GePlacemarkManager.prototype.destroy = function() {
//	alert('startpoints');
	google.earth.removeEventListener(ge.getView(), 'viewchangeend', this.setATimeout_);
	google.earth.removeEventListener(ge.getWindow(), 'mousedown', this.mapClick_);
	
	this.placemarksInView_ = [];
	for(var i=0; i<GePlacemarkManager.NUMBER_COLS_; i++) {
		this.placemarksInView_[i] = [];
	}

	this.leftoverPoints_ = [];
	this.outsideGridPoints_ = [];
	this.gridPoints_ = [];

	for (var i=0; i<this.allPoints_.length; i++) {
		ge.getFeatures().removeChild(this.allPoints_[i].getPlacemark());
	}

	this.allPoints_ = [];
//	alert('donepoints');
};

GePlacemarkManager.prototype.updatePoints_ = function() {
	var n = this.viewportNorthBound_;
	var s = this.viewportSouthBound_;
	var e = this.viewportEastBound_;
	var w = this.viewportWestBound_;

	this.updateViewportBounds_();

	// alert(n + ' '  + this.viewportNorthBound_ + ' ' + s + ' ' + this.viewportSouthBound_ + ' ' + e + ' ' + + this.viewportEastBound_ + ' ' + w + ' ' + this.viewportWestBound_);
	// alert(this.gridPoints_.length + ' ' + this.outsideGridPoints_.length + ' ' + this.leftoverPoints_.length);
	this.placemarksInView_ = [];
	for(var i=0; i<GePlacemarkManager.NUMBER_COLS_; i++) {
		this.placemarksInView_[i] = [];
	}

	if(this.viewportNorthBound_ < n && this.viewportSouthBound_ > s && this.viewportEastBound_ < e && this.viewportWestBound_ > w) {
		// alert('zoom');
		var copyGridPoints = this.gridPoints_.slice(0);
		this.gridPoints_ = [];
		for(var i=0; i<copyGridPoints.length; i++) {
			this.addPoint(copyGridPoints[i]);
		}
	} else if (this.viewportNorthBound_ < this.outsideNorthBound_ 
			&& this.viewportSouthBound_ > this.outsideSouthBound_ 
			&& this.viewportEastBound_ < this.outsideEastBound_ 
			&& this.viewportWestBound_ > this.outsideWestBound_) {
		// alert(this.viewportNorthBound_ + ' '  + this.outsideNorthBound_ + ' ' + this.viewportSouthBound_ + ' ' + this.outsideSouthBound_ + ' ' + this.viewportEastBound_ + ' ' + this.outsideEastBound_ + ' ' + this.viewportWestBound_ + ' ' + this.outsideWestBound_);
		// alert('pan');
		var copyOutsideGridPoints = this.gridPoints_.concat(this.outsideGridPoints_);

		this.gridPoints_ = [];
		this.outsideGridPoints_ = [];
		
		for(var i=0; i<copyOutsideGridPoints.length; i++) {
			this.addPoint(copyOutsideGridPoints[i]);
		}
		
	} else {
		// alert(this.gridPoints_.length + ' ' + this.outsideGridPoints_.length + ' ' + this.leftoverPoints_.length);
		// alert('reset');
		this.updateOutsideBounds_();
		
		this.gridPoints_ = [];
		this.outsideGridPoints_ = [];
		this.leftoverPoints_ = [];
		this.placemarksInView_ = [];
		for(var i=0; i<GePlacemarkManager.NUMBER_COLS_; i++) {
			this.placemarksInView_[i] = [];
		}

		for(var i=0; i<this.allPoints_.length; i++) {
			this.addPoint(this.allPoints_[i]);
		}
	}
};

/*
 * add points
 */
GePlacemarkManager.prototype.addPoints = function(points) {
	this.allPoints_ = points.slice(0);
	
	for (var i=0; i<points.length; i++) {
		ge.getFeatures().appendChild(points[i].getPlacemark());
		points[i].setSeen(0);
	}
	
	this.updatePoints_();
};

GePlacemarkManager.prototype.addPoint = function(point) {
	var lat = point.getLat();
	var lng = point.getLng();
	
	var n = this.viewportNorthBound_;
	var s = this.viewportSouthBound_;
	var w = this.viewportWestBound_;
	var e = this.viewportEastBound_;
	
	// alert(Number(this.viewportSouthBound_ + this.outsideViewport_));
	
	if(lat > s && lat < n && lng > w && lng < e) {
		this.addToGridPoints_(point);
		return;
	} else if(lat > this.outsideSouthBound_ 
			&& lat < this.outsideNorthBound_ 
			&& lng > this.outsideWestBound_ 
			&& lng < this.outsideEastBound_) {
		this.addToOutsideGridPoints_(point);
		return;
	} else {
		this.addToLeftoverPoints_(point);
		return;
	}
};

/*
 * add to map
 */
GePlacemarkManager.prototype.addToGridPoints_ = function(point) {
	var n = this.viewportNorthBound_;
	var s = this.viewportSouthBound_;
	var e = this.viewportEastBound_;
	var w = this.viewportWestBound_;

	var colBase = ((e-w)/GePlacemarkManager.NUMBER_COLS_);
	
	var col = -1;

	for(var i=1; i<=GePlacemarkManager.NUMBER_COLS_; i++) {
		// alert(colBase + ' ' + point.getLng() + ' ' + ((i*colBase)+w));
		if(point.getLng() > ((i*colBase)+w)) {
			continue;
		} else {
			this.placemarksInView_[i-1].push(point);
			if(this.placemarksInView_[i-1].length < 10) {
				if(!point.isSeen()) {
					point.setSeen(1);
				}
			} else {
				point.setSeen(0);
			}
			break;
		}
	}
	
	this.gridPoints_.push(point);
};

GePlacemarkManager.prototype.addToOutsideGridPoints_ = function(point) {
	if(point.isSeen())
		point.setSeen(0);	
	this.outsideGridPoints_.push(point);
};

/*
 * add to leftovers
 */
GePlacemarkManager.prototype.addToLeftoverPoints_ = function(point) {
	if(point.isSeen())
		point.setSeen(0);
	this.leftoverPoints_.push(point);
};

GePlacemarkManager.prototype.getLeftoverCount = function() {
	return this.leftoverPoints_.length;
};

GePlacemarkManager.prototype.getGridCount = function() {
	return this.gridPoints_.length;
};

/*
 * update viewport bounds
 */
GePlacemarkManager.prototype.updateViewportBounds_ = function() {
	this.viewportNorthBound_ = this.ge_.getView().getViewportGlobeBounds().getNorth();
	this.viewportSouthBound_ = this.ge_.getView().getViewportGlobeBounds().getSouth();
	this.viewportEastBound_ = this.ge_.getView().getViewportGlobeBounds().getEast();
	this.viewportWestBound_ = this.ge_.getView().getViewportGlobeBounds().getWest();
};

GePlacemarkManager.prototype.updateOutsideBounds_ = function() {
	this.outsideNorthBound_ = this.viewportNorthBound_ + GePlacemarkManager.OUTSIDE_BOUNDS_;
	this.outsideSouthBound_ = this.viewportSouthBound_ - GePlacemarkManager.OUTSIDE_BOUNDS_;
	this.outsideEastBound_ = this.viewportEastBound_ + GePlacemarkManager.OUTSIDE_BOUNDS_;
	this.outsideWestBound_ = this.viewportWestBound_ - GePlacemarkManager.OUTSIDE_BOUNDS_;
};

GePlacemarkManager.prototype.onMapMoveEnd_ = function () {
	var me = this;
	me.objectSetTimeout_(this, this.updatePoints_, 100);
};

GePlacemarkManager.prototype.objectSetTimeout_ = function (object, command, milliseconds) {
	return window.setTimeout(function () {
		command.call(object);
	}, milliseconds);
};

GePlacemarkManager.prototype.setSeen = function(visibility) {
//	for(var i=0; i<this.gridPoints_.length; i++) {
//		this.gridPoints_[i].setSeen(visibility);
//	}
	for(var i=0; i<GePlacemarkManager.NUMBER_COLS_; i++) {
		for(var j=0; j<this.placemarksInView_[i].length; j++) {
			this.placemarksInView_[i][j].setSeen(visibility);
		}
	}
};

GePlacemarkManager.prototype.setInfoBalloon_ = function(responseText, responseStatus, responseXML, target, object) {
};


