function GraphicManager(mapObj, idMapContainer, distanceUnit) {   
this.veMap = mapObj;//Real Ve Map object
this.idMapContainer = idMapContainer;
this.evalOnDrawEnd = null;
this.scaleBarDistanceUnit = distanceUnit;//Distance unit (kilometers or miles)

slDrawing = null;//Layer used to draw shape
myGeomType = null;//Variable used to specify the type of shape by drawing
myPoints = null;
tempPoints = null;
myDistance = 0;
tempDistance = 0;
myCurrentShape = null;
myCirclePoints = null;//Array containing the points (latLong) used to draw the circle
tempShape = null;
tempCircle = null; 

//### Methods ############## 
this.Reset = function(){
if(slDrawing==null) {
slDrawing = new VEShapeLayer();
graphicManager.GetMap().AddShapeLayer(slDrawing);
} 
try {                         
slDrawing.DeleteShape(tempShape);
slDrawing.DeleteShape(tempCircle);
}
catch (VEException) {}

tempShape = null;
tempCircle = null;     
myCirclePoints = null;
myGeomType = null;
myPoints = new Array();
tempPoints = null;
myDistance = 0;
tempDistance = 0;
myCurrentShape = null;  
getById(idMapContainer).style.cursor = 'url(http://dev.virtualearth.net/mapcontrol/v6/cursors/grab.cur), move';
graphicManager.GetMap().DetachEvent("onmousemove", graphicManager.DrawMouseMove);
graphicManager.GetMap().DetachEvent("onclick", graphicManager.DrawMouseClick);  
graphicManager.GetMap().DetachEvent("onmousemove", graphicManager.MouseMove);
getById('divDistance').style.visibility="hidden";
}

this.DrawPoint = function(){this.Draw('point');} 
this.DrawPolyline = function(){this.Draw('polyline');}  
this.DrawPolygon = function(){this.Draw('polygon');} 
this.DrawCircle = function(){this.Draw('circle');}     
this.GetMap = function(){return this.veMap;}

this.Draw = function(geomType){
graphicManager.Reset();
myGeomType = geomType;
graphicManager.GetMap().AttachEvent("onclick", graphicManager.DrawMouseClick);
graphicManager.GetMap().AttachEvent("onmousemove", graphicManager.MouseMove);
}

this.DrawMouseClick = function(e){
getById(idMapContainer).style.cursor = 'crosshair';
var pixel = new VEPixel(e.mapX, e.mapY);
var latLong = graphicManager.GetMap().PixelToLatLong(pixel);

if (myPoints.length == 0 && myGeomType != 'point') {      
graphicManager.GetMap().DetachEvent("onmousemove", graphicManager.MouseMove);
graphicManager.GetMap().AttachEvent("onmousemove", graphicManager.DrawMouseMove);    
}       
if ((myGeomType == 'circle') && (myPoints.length == 2)) {
myPoints[1] = latLong;
myDistance = tempDistance;
}
else {
myPoints.push(latLong);
myDistance += tempDistance;
}        
tempDistance = 0;       
if (e.rightMouseButton) {      
myDistance = Math.round(myDistance * 1000)/ 1000;  
var descriptionCurrentShape = "";
var actionCurrentShape = "";
if((myGeomType == 'polygon') && (myPoints.length >= 3)) {          
myCurrentShape = new VEShape(VEShapeType.Polygon, myPoints);
descriptionCurrentShape = MESSAGES['graphic.perimeter'] + ": " + myDistance + (graphicManager.scaleBarDistanceUnit == 'k' ? " km" : " mi");          
} 
if((myGeomType == 'polyline') && (myPoints.length >= 2)) {
myCurrentShape = new VEShape(VEShapeType.Polyline, myPoints);
descriptionCurrentShape = MESSAGES['graphic.distance'] + ": " + myDistance + (graphicManager.scaleBarDistanceUnit == 'k' ? " km" : " mi");
} 
if((myGeomType == 'circle') && (myCirclePoints != null)) {
myCurrentShape = new VEShape(VEShapeType.Polygon, myCirclePoints);
descriptionCurrentShape = MESSAGES['graphic.radius'] + ": " + myDistance + (graphicManager.scaleBarDistanceUnit == 'k' ? " km" : " mi"); 
} 
if(myGeomType == 'point')
myCurrentShape = new VEShape(VEShapeType.Pushpin, latLong);     

if(myCurrentShape != null){
//Set information myCurrentShape and add to slDrawing layer              
myCurrentShape.SetTitle("<h3>" + MESSAGES[myCurrentShape.GetType()] + "</h3>");
var customIconSpec = new VECustomIconSpecification();
customIconSpec.CustomHTML = 'images/pushpins/pushpin.png';
myCurrentShape.SetCustomIcon(customIconSpec);
slDrawing.AddShape(myCurrentShape);

//Add the possible actions in the shape description
actionCurrentShape += (descriptionCurrentShape == "" ? "" : "<br/><br/>"); 
actionCurrentShape += '<a class="deletePoi" href="javascript:graphicManager.Delete(\'' + myCurrentShape.GetID() + '\');">' + MESSAGES['graphic.delete'] + '</a>';
actionCurrentShape += '<br/><br/>';
var lat = (myGeomType == 'point') ? latLong.Latitude : null;
var lon = (myGeomType == 'point') ? latLong.Longitude : null;
actionCurrentShape += '<a class="linkSave" href="javascript:addGraphicToPoiUser(' + lat + ',' + lon + ',\'' + myCurrentShape.GetType() + '\', \'' + graphicManager.GetCircleStringCoords(myPoints) + '\', \'' + descriptionCurrentShape + '\'); graphicManager.Delete(\'' + myCurrentShape.GetID() + '\', false);">' + MESSAGES['grapghic.lbl.savedrawtopoiuser'] + "</a>";

myCurrentShape.SetDescription(descriptionCurrentShape + actionCurrentShape);
graphicManager.GetMap().ShowInfoBox(myCurrentShape);
}           
if( graphicManager.evalOnDrawEnd != null )
eval(graphicManager.evalOnDrawEnd);        
}
}

this.MouseMove = function(e){
getById(idMapContainer).style.cursor = 'crosshair';
var pixel = new VEPixel(e.mapX, e.mapY);
var latLong = graphicManager.GetMap().PixelToLatLong(pixel);   
graphicManager.SetDivContent(e.clientY, e.clientX, latLong);
}

this.DrawMouseMove = function(e){
getById(idMapContainer).style.cursor = 'crosshair';
var pixel = new VEPixel(e.mapX, e.mapY);
var latLong = graphicManager.GetMap().PixelToLatLong(pixel);        
tempPoints = myPoints.slice(0, myPoints.length);

if ((myGeomType == 'circle') && (tempPoints.length == 2)) {
tempPoints[1] = latLong;
tempDistance = getDistance(tempPoints[0], latLong, graphicManager.scaleBarDistanceUnit);
}
else {
tempPoints.push(latLong);
tempDistance = getDistance(tempPoints[myPoints.length-1], latLong, graphicManager.scaleBarDistanceUnit);
}

graphicManager.SetDivContent(e.clientY, e.clientX, latLong);

try {
slDrawing.DeleteShape(tempShape);
slDrawing.DeleteShape(tempCircle);
}
catch (VEException) {
}

if (tempPoints.length == 2) {     
//Draw radius line for circle or line if polyline/polygon
tempShape = new VEShape(VEShapeType.Polyline, tempPoints);
tempShape.HideIcon();
slDrawing.AddShape(tempShape);
if (myGeomType == 'circle') {
var R = 6371; // earth's mean radius in km
var lat = (tempPoints[0].Latitude * Math.PI) / 180; //rad
var lon = (tempPoints[0].Longitude * Math.PI) / 180; //rad
var d = parseFloat(tempDistance) / R;  // d = angular distance covered on earth's surface 
myCirclePoints = getCirclePoints(tempPoints[0], tempPoints[1]);
tempCircle = new VEShape(VEShapeType.Polygon, myCirclePoints);
tempCircle.HideIcon();
slDrawing.AddShape(tempCircle);
} 
}

if (tempPoints.length > 2) {
if(myGeomType == 'polygon')
tempShape = new VEShape(VEShapeType.Polygon, tempPoints);     
if(myGeomType == 'polyline')
tempShape = new VEShape(VEShapeType.Polyline, tempPoints);

tempShape.HideIcon();
slDrawing.AddShape(tempShape);
}
}

this.Delete = function(idShape, askConfirm){
if(askConfirm==null )
askConfirm = true;
var response = true;
if(askConfirm)
response = confirm(MESSAGES['message.askremovelement']);
if(response)
slDrawing.DeleteShape(slDrawing.GetShapeByID(idShape));    
}

this.GetStringCoordsShape = function(idShape){return this.GetStringCoords(slDrawing.GetShapeByID(idShape));}   
this.GetStringCoords = function(shape){
var points = shape.GetPoints();
var content = "";
for(i=0; i < points.length; i++) {
content += points[i].Latitude + ";" + points[i].Longitude + "|";
}  
return content;
}

this.GetCircleStringCoords = function(myPoints){
var content="";
for(i=0; i < myPoints.length; i++) {
content += myPoints[i].Latitude + ";" + myPoints[i].Longitude + "|";
}  
return content;
}

this.SetDivContent = function(top, left, latLong){
var element = getById('divDistance');
element.style.visibility = "visible";
element.style.left = (left + 30) + "px";
element.style.top = (top + 30) + "px";
var content = "";
if(myGeomType != 'point') { 
if(myGeomType == 'polygon')
content += "<b>" + MESSAGES['graphic.perimeter'] + ":</b> ";
if(myGeomType == 'polyline')
content += "<b>" + MESSAGES['graphic.distance'] + ":</b> ";
if(myGeomType == 'circle')
content += "<b>" + MESSAGES['graphic.radius'] + ":</b> ";     
content += (Math.round((myDistance + tempDistance) * 1000) / 1000) + (graphicManager.scaleBarDistanceUnit == 'k' ? " km" : " mi") + "<br/>";
}

content += "<b>Lat:</b> " + latLong.Latitude + "<br/>" + "<b>Long:</b> " + latLong.Longitude;
content += "<hr>";

if(myGeomType == 'point')
content += MESSAGES['help.drawpoint'];
if(myGeomType == 'polygon')
content += MESSAGES['help.drawpolygon'];
if(myGeomType == 'polyline')
content += MESSAGES['help.drawpolyline'];
if(myGeomType == 'circle')
content += MESSAGES['help.drawcircle'];

element.innerHTML = content;  
}
}