/**
* CHZERO.Control.Cns<br/>
*
* @class Cns
* @extends OpenLayers.Control
* @constructor
* @namespace CHZERO.Control
* @param {Object} options 옵션 hashtable
*/
CHZERO.Control.Cns = OpenLayers.Class(OpenLayers.Control.Panel, {
/**
* show / hide
* @property isShow
* @type {Boolean}
*/
isShow: true,
sourcePoint: null,
destinationPoint: null,
/*searchCns: null,*/
cnsLayer: null,
selectFeatureControl: null,
/**
* 출발지 아이콘 등 스타일
* @property sourceStyle
* @type {Object}
*/
sourceStyle: {
externalGraphic: CHZERO.webUrl + '/image/mark_start_on.png', graphicWidth: 59, graphicHeight: 70, graphicYOffset: -70
},
/**
* 도착지 아이콘 등 스타일
* @property destinationStyle
* @type {Object}
*/
destinationStyle: {
externalGraphic: CHZERO.webUrl + '/image/mark_end_on.png', graphicWidth: 59, graphicHeight: 70, graphicYOffset: -70
},
/**
* 경유지 아이콘 등 스타일
* @property routeStyle
* @type {Object}
*/
routeStyle: {
externalGraphic: CHZERO.webUrl + '/image/mark_pass_on.png', graphicWidth: 59, graphicHeight: 70, graphicYOffset: -70
},
sourceLonLat: null,
destinationLonLat: null,
/**
* 경유지 array
* @property routes
* @type {Array(OpenLayers.Feature.Vector)}
*/
routes: [],
/**
* 단순화 tolerance
* @property tolerance
* @type {Float}
*/
tolerance: 0.1,
/**
* 단순화 여부
* @property isSimplify
* @type {Boolean}
*/
isSimplify: false,
/**
* fit bounds
* @property isAutoScale
* @type {Boolean}
*/
isAutoScale: true,
/**
* search callback
* @property searchCallback
* @type {Function}
*/
searchCallback: null,
/**
* 출발지 클릭 이벤트 콜백함수
* @property sourceCallback
* @type {Function}
*/
sourceCallback: null,
/**
* 도착지 클릭 이벤트 콜백함수
* @property sourceCallback
* @type {Function}
*/
destinationCallback: null,
/**
* 디폴트 최적 모드 CHZERO.Control.Cns.BEST_TYPE
* @property cnsType
* @type {String}
*/
cnsType: '0',
sndCode: ["안내없음",
"직진",
"1시 방향 우회전",
"2시 방향 우회전",
"우회전",
"4시 방향 우회전",
"5시 방향 우회전",
"7시 방향 좌회전",
"8시 방향 좌회전",
"좌회전",
"10시 방향 좌회전",
"11시 방향 좌회전",
"직진 방향에 고가도로 진입",
"오른쪽 방향에 고가도로 진입",
"왼쪽 방향에 고가도로 진입",
"지하차도",
"오른쪽 방향에 고가도로 옆 도로",
"왼쪽 방향에 고가도로 옆 도로",
"오른쪽 방향에 지하차도 옆 도로",
"왼쪽 방향에 지하차도 옆 도로",
"오른쪽 도로",
"왼쪽 도로",
"직진 방향에 고속도로 진입",
"오른쪽 방향에 고속도로 진입",
"왼쪽 방향에 고속도로 진입",
"직진 방향에 도시고속도로 진입",
"오른쪽 방향에 도시고속도로 진입",
"왼쪽 방향에 도시고속도로 진입",
"오른쪽 방향에 고속도로 출구",
"왼쪽 방향에 고속도로 출구",
"오른쪽 방향에 도시고속도로 출구",
"왼쪽 방향에 도시고속도로 출구",
"분기점에서 직진",
"분기점에서 오른쪽",
"분기점에서 왼쪽",
"U-turn",
"요금소",
"직진 방향에 고속도로 출구",
"직진 방향에 도시고속도로 출구"],
/**
* 출발지나 도착지 경유지 drag 후에 콜백 이벤트
* @method onCompleted
* @param {OpenLayers.Feature} feature
* @param {OpenLayers.Pixel} pixel
*/
onCompleted: function(feature, pixel) { },
destroy: function() {
OpenLayers.Control.Panel.prototype.destroy.apply(this, arguments);
this.sourcePoint = null;
this.destinationPoint = null;
this.sourceStyle = null;
this.destinationStyle = null;
this.searchCallback = null;
this.sourceCallback = null;
this.destinationCallback = null;
this.sndCode = null;
var r = this.routes.pop();
while (r) {
r = this.routes.pop();
}
this.routes = null;
},
sourceClick: function(evt) {
var geom = evt.geometry.clone();
geom.transform(this.map.getProjectionObject(), this.map.displayProjection);
this.cns.sourceLonLat = new OpenLayers.LonLat(geom.x, geom.y);
this.cns.pinShow(this.vector, new OpenLayers.LonLat(evt.geometry.x, evt.geometry.y));
if (this.cns.sourceCallback && typeof this.cns.sourceCallback === 'function') this.cns.sourceCallback(evt);
/*this.cns.search();*/
},
destinationClick: function(evt) {
var geom = evt.geometry.clone();
geom.transform(this.map.getProjectionObject(), this.map.displayProjection);
this.cns.destinationLonLat = new OpenLayers.LonLat(geom.x, geom.y);
this.cns.pinShow(this.vector, new OpenLayers.LonLat(evt.geometry.x, evt.geometry.y));
if (this.cns.destinationCallback && typeof this.cns.destinationCallback === 'function') this.cns.destinationCallback(evt);
/*this.cns.search();*/
},
/**
* feature 그리기
* @method pinShow
* @param {OpenLayers.Feature} vector
* @param {OpenLayers.LonLat} lonLat
*/
pinShow: function(vector, lonLat) {
if (vector) {
this.cnsLayer.removeFeatures(vector);
if (lonLat) vector.geometry = new OpenLayers.Geometry.Point(lonLat.lon, lonLat.lat);
this.cnsLayer.addFeatures([vector]);
this.cnsLayer.redraw();
}
},
/**
* feature 제거
* @method removePin
* @param {OpenLayers.Feature} vector
*/
removePin: function(vector) {
this.cnsLayer.removeFeatures(vector);
vector.geometry = null;
},
createStyleMap: function(style) {
cnsStyle = new OpenLayers.Style();
cnsStyle.addRules([new OpenLayers.Rule({ symbolizer: style })]);
return new OpenLayers.StyleMap({ 'default': cnsStyle });
},
createCnsVectorLayer: function() {
ly = new CHZERO.Layer.ZeroMapVector('Cns Zeromap Layer');
cnsSymbolizers = {
'Point': {
pointRadius: 5,
graphicName: 'square',
fillColor: 'white',
fillOpacity: 0.8,
strokeWidth: 1,
strokeOpacity: 1,
strokeColor: '#333333',
labelSelect: true,
fontWeight: 'bold'
},
'Line': {
strokeWidth: 6,
strokeOpacity: 0.8,
strokeColor: '#FF0000'
},
'Polygon': {
strokeWidth: 2,
strokeOpacity: 1,
strokeColor: '#666666',
fillColor: 'red',
fillOpacity: 0.3
}
};
cnsRules = [
new OpenLayers.Rule({ symbolizer: cnsSymbolizers }),
new OpenLayers.Rule({
minScaleDenominator: 200000000,
symbolizer: {
'Point': {
pointRadius: 3,
fontSize: '3px',
label: null
}
}
}),
new OpenLayers.Rule({
maxScaleDenominator: 200000000,
minScaleDenominator: 640000,
symbolizer: {
'Point': {
pointRadius: 4,
fontSize: '8px',
label: null
},
'Line': {
strokeWidth: 4
}
}
}),
new OpenLayers.Rule({
maxScaleDenominator: 640000,
minScaleDenominator: 80000,
symbolizer: {
'Point': {
pointRadius: 5,
fontSize: '10px',
label: null
},
'Line': {
strokeWidth: 5
}
}
}),
new OpenLayers.Rule({
maxScaleDenominator: 80000,
minScaleDenominator: 40000,
symbolizer: {
'Point': {
pointRadius: 6,
fontSize: '12px',
label: null
},
'Line': {
strokeWidth: 6
}
}
}),
new OpenLayers.Rule({
maxScaleDenominator: 40000,
minScaleDenominator: 10000,
symbolizer: {
'Point': {
pointRadius: 8,
fontSize: '15px',
label: null
},
'Line': {
strokeWidth: 8
}
}
}),
new OpenLayers.Rule({
maxScaleDenominator: 10000,
symbolizer: {
'Point': {
pointRadius: 10,
fontSize: '18px',
label: null
},
'Line': {
strokeWidth: 10
}
}
})];
cnsStyle = new OpenLayers.Style();
cnsStyle.addRules(cnsRules);
selectCnsRules = [];
selectCnsRules[0] = new OpenLayers.Rule({ symbolizer: {
pointRadius: 6,
graphicName: 'square',
fillColor: 'blue',
fillOpacity: 0.5,
strokeWidth: 1,
strokeOpacity: 1,
strokeColor: '#333333'
}
});
for (var i = 1; i < cnsRules.length; i++) {
selectCnsRules[i] = cnsRules[i];
}
selectCnsStyle = new OpenLayers.Style();
selectCnsStyle.addRules(selectCnsRules);
cnsStyleMap = new OpenLayers.StyleMap({ 'default': cnsStyle, 'select': selectCnsStyle });
ly.styleMap = cnsStyleMap;
return ly;
},
initialize: function(options) {
if (!options) options = {};
if (!options['displayClass']) options['displayClass'] = 'czControlCns';
OpenLayers.Control.Panel.prototype.initialize.apply(this, [options]);
this.sourcePoint = new CHZERO.Control.CnsPoint(CHZERO.Control.CnsPoint.POINT_TYPES.Source,
{ title: '출발지',
handlerOptions: { layerOptions: { styleMap: this.createStyleMap(this.sourceStyle)} },
vector: new OpenLayers.Feature.Vector(null, null, this.sourceStyle),
cns: this
});
this.sourcePoint.vector.isUnselect = true;
this.sourcePoint.vector.enabledDrag = true;
this.destinationPoint = new CHZERO.Control.CnsPoint(CHZERO.Control.CnsPoint.POINT_TYPES.Destination,
{ title: '도착지',
handlerOptions: { layerOptions: { styleMap: this.createStyleMap(this.destinationStyle)} },
vector: new OpenLayers.Feature.Vector(null, null, this.destinationStyle),
cns: this
});
this.destinationPoint.vector.isUnselect = true;
this.destinationPoint.vector.enabledDrag = true;
/*this.searchCns = new OpenLayers.Control.Button({
title: '길찾기',
displayClass: 'czControlCnsSearch',
trigger: this.search,
cns: this
});*/
this.addControls([this.sourcePoint, this.destinationPoint/*, this.searchCns*/]);
},
/**
* show
* @method show
*/
show: function() {
if (this.map) {
if (this.cnsLayer && this.map.getLayerIndex(this.cnsLayer) == -1)
this.map.addLayer(this.cnsLayer);
if (this.selectFeatureControl && this.map.getControl(this.selectFeatureControl.id) == null)
this.map.addControl(this.selectFeatureControl);
if (this.dragFeature && this.map.getControl(this.dragFeature.id) == null)
this.map.addControl(this.dragFeature);
}
this.div.style.display = 'block';
/*$('.' + this.displayClass + ' div').css('display', 'block');*/
this.isShow = true;
},
/**
* hide
* @method hide
*/
hide: function() {
this.div.style.display = 'none';
/*$('.' + this.displayClass + ' div').css('display', 'none');*/
if (this.map) {
if (this.cnsLayer && this.map.getLayerIndex(this.cnsLayer) > -1)
this.map.removeLayer(this.cnsLayer);
if (this.selectFeatureControl && this.map.getControl(this.selectFeatureControl.id) != null)
this.map.removeControl(this.selectFeatureControl);
if (this.dragFeature && this.map.getControl(this.dragFeature.id) != null)
this.map.removeControl(this.dragFeature);
}
this.isShow = false;
},
/**
* @method activate
* @return {Boolean} alreadyActivate
*/
activate: function() {
if (OpenLayers.Control.Panel.prototype.activate.apply(this, arguments)) {
this.cnsLayer = this.createCnsVectorLayer();
this.map.addLayer(this.cnsLayer);
this.selectFeatureControl = new CHZERO.Control.ZeroMapSelectFeature(this.cnsLayer, { cns: this, hover: true, clickout: true });
this.map.addControl(this.selectFeatureControl);
this.selectFeatureControl.activate();
this.dragFeature = new CHZERO.Control.ZeroMapDragFeature(this.cnsLayer, { cns: this, onCompleted: this.onCompleted });
this.map.addControl(this.dragFeature);
this.dragFeature.activate();
this.sourcePoint.events.on({
click: this.sourceClick
});
this.destinationPoint.events.on({
click: this.destinationClick
});
this.isShow = true;
return true;
}
else {
return false;
}
},
/**
* @method deactivate
* @return {Boolean} alreadyDeactivate
*/
deactivate: function() {
if (OpenLayers.Control.Panel.prototype.deactivate.apply(this, arguments)) {
this.clear();
this.selectFeatureControl.deactivate();
this.map.removeControl(this.selectFeatureControl);
this.selectFeatureControl.destroy();
this.selectFeatureControl = null;
this.dragFeature.deactivate();
this.map.removeControl(this.dragFeature);
this.dragFeature.destroy();
this.dragFeature = null;
if (this.map.getLayerIndex(this.cnsLayer) > -1) {
this.map.removeLayer(this.cnsLayer);
}
this.cnsLayer.destroy();
this.cnsLayer = null;
this.sourcePoint.events.un({
click: this.sourceClick
});
this.destinationPoint.events.un({
click: this.destinationClick
});
this.sourceLonLat = null;
this.destinationLonLat = null;
this.sourcePoint.vector.geometry = null;
this.destinationPoint.vector.geometry = null;
this.isShow = false;
return true;
}
else return false;
},
/**
* 지우기
* @method clear
*/
clear: function() {
var control;
if (this.controls) {
for (var i = 0, len = this.controls.length; i < len; i++) {
control = this.controls[i];
control.deactivate();
}
}
var features = this.cnsLayer.features;
var feat = null;
for (var i = 0; i < features.length; i++) {
/*feat = features[i];
if (feat.popup) {
this.map.removePopup(feat.popup);
feat.popup.destroy();
feat.popup = null;
}*/
}
this.cnsLayer.removeAllFeatures();
for (var i = 0; i < this.map.popups.length; i++) {
this.map.popups[i].hide();
}
/*while (this.map.popups.length) {
var obj = this.map.popups.pop();
this.map.removePopup(obj);
}*/
},
/**
* 길찾기
* @method search
* @param {Function} callback callback function
* @return {Boolean} isValidate
*/
search: function(c) {
var cns = (this instanceof CHZERO.Control.Cns) ? this : this.cns;
var cb = (c && typeof c === 'function') ? c : this.searchCallback;
var routes = cns.routes;
cns.clear();
if (!cns.sourceLonLat) {
for (var i = 0; i < routes.length; i++) {
cns.pinShow(routes[i]);
}
cns.pinShow(cns.sourcePoint.vector);
cns.pinShow(cns.destinationPoint.vector);
cns.sourcePoint.activate();
return false;
}
if (!cns.destinationLonLat) {
for (var i = 0; i < routes.length; i++) {
cns.pinShow(routes[i]);
}
cns.pinShow(cns.sourcePoint.vector);
cns.pinShow(cns.destinationPoint.vector);
cns.destinationPoint.activate();
return false;
}
var startFeat = { type: 'Feature',
geometry: { type: 'Point', coordinates: [cns.sourceLonLat.lon, cns.sourceLonLat.lat] },
properties: { name: 'start' }
};
var endFeat = { type: 'Feature',
geometry: { type: 'Point', coordinates: [cns.destinationLonLat.lon, cns.destinationLonLat.lat] },
properties: { name: 'end' }
};
var features = [startFeat, endFeat];
for (var i = 0; i < routes.length; i++) {
var geom = routes[i].geometry.clone();
geom.transform(cns.map.getProjectionObject(), cns.map.displayProjection);
features.push({
type: 'Feature',
geometry: { type: 'Point', coordinates: [geom.x, geom.y] },
properties: { name: 'route' }
});
}
/*option = 0 최적 1 최단 2 고속 3 무료*/
var featureCollection = { type: 'FeatureCollection', features: features
, properties: { option: this.cnsType }
};
var req = new OpenLayers.Protocol.Script({
url: CHZERO.webUrl + '/GetCNSJson.aspx',
params: {
'data': JSON.stringify(featureCollection),
'ver': CHZERO.version,
'authKey': CHZERO.authKey,
'varName': this.map.globalVarName
},
callback: function(res) {
var data = res.data;
var map = this.map;
var callbackFun = (cb && typeof cb === 'function') ? cb(data) : (function(data) {
if ('undefined' != typeof (data)) {
var geojson_format = new OpenLayers.Format.GeoJSON();
var collection = geojson_format.read(data);
var cnsPanel = map.cns;
if (data.properties) {
if (data.properties.status == 'error') {
if (data.properties.statusDetail == '출발지 이상') {
cnsPanel.pinShow(cnsPanel.destinationPoint.vector);
cnsPanel.sourcePoint.activate();
} else if (data.properties.statusDetail == '도착지 이상') {
cnsPanel.pinShow(cnsPanel.sourcePoint.vector);
cnsPanel.destinationPoint.activate();
} else if (data.properties.statusDetail == '경유지 이상') {
cnsPanel.pinShow(cnsPanel.sourcePoint.vector);
cnsPanel.pinShow(cnsPanel.destinationPoint.vector);
cnsPanel.removeAllRoutePoint();
}
alert(data.properties.statusDetail);
}
else {
/*cnsPanel.selectFeatureControl.activate();*/
var tempArr = [];
var cnsType = null;
for (var i = 0; i < collection.length; i++) {
collection[i].geometry.transform(map.displayProjection, map.getProjectionObject());
cnsType = collection[i].data.cnsType;
if (cnsType == "yudo") {
collection[i].enabledHover = true;
var prop = collection[i].data;
var road = '';
if (prop.cross) {
road += prop.cross;
if (prop.road)
road += '(' + prop.road + ')';
}
else {
road += prop.road;
}
if (prop.codeDetail) road += ' ' + prop.codeDetail;
var dist = (prop.frontDistance / 1000).toFixed(2);
prop.overContentHtml = '<div class="box">' + collection[i].data.index + '. ' + collection[i].data.road + ' ' + collection[i].data.cross + '</div>';
prop.overSize = new OpenLayers.Size(prop.overContentHtml.length * 10, CHZERO.isIE ? 28 : 18);
prop.clickContentHtml = '<div class="box">' + prop.index + '. ' + road + '</div>';
}
else if (cnsType == "extra") {
collection[i].isUnselect = true;
}
else {
tempArr.push(collection[i]);
collection[i].isUnselect = true;
if (this.isSimplify)
collection[i].geometry = collection[i].geometry.simplify(cnsPanel.tolerance);
}
cnsPanel.cnsLayer.addFeatures(collection[i]);
}
cnsPanel.pinShow(cnsPanel.sourcePoint.vector);
cnsPanel.pinShow(cnsPanel.destinationPoint.vector);
ex = cnsPanel.cnsLayer.getDataExtent();
if (cnsPanel.isAutoScale && ex != null) {
map.zoomToExtent(ex);
map.zoomOut();
}
map.setCenter(ex.getCenterLonLat());
}
}
}
} ());
}
});
req.read();
return true;
},
/**
* 출발지 지정
* @method setSourcePoint
* @param {Float} lon
* @param {Float} lat
*/
setSourcePoint: function(lon, lat) {
var map = this.map;
var lonLat = new OpenLayers.LonLat(lon, lat);
var cLonLat = lonLat.clone();
cLonLat.transform(map.getProjectionObject(), map.displayProjection);
this.sourceLonLat = cLonLat;
this.pinShow(this.sourcePoint.vector, lonLat);
this.sourcePoint.deactivate();
this.destinationPoint.deactivate();
},
/**
* 도착지 지정
* @method setDestinationPoint
* @param {Float} lon
* @param {Float} lat
*/
setDestinationPoint: function(lon, lat) {
var map = this.map;
var lonLat = new OpenLayers.LonLat(lon, lat);
var cLonLat = lonLat.clone();
cLonLat.transform(map.getProjectionObject(), map.displayProjection);
this.destinationLonLat = cLonLat;
this.pinShow(this.destinationPoint.vector, lonLat);
this.sourcePoint.deactivate();
this.destinationPoint.deactivate();
},
/**
* 경유지 추가
* @method addRoutePoint
* @param {Float} lon
* @param {Float} lat
*/
addRoutePoint: function(lon, lat) {
if (CHZERO.Control.Cns.ROUTE_MAX_SIZE > this.routes.length) {
var v = new OpenLayers.Feature.Vector(null, null, this.routeStyle);
v.enabledDrag = true;
var l = new OpenLayers.LonLat(lon, lat);
this.pinShow(v, l);
this.routes.push(v);
}
},
/**
* 해당 인덱스 경유지 제거
* @method removeRoutePoint
* @param {Integer} idx index
*/
removeRoutePoint: function(idx) {
if (idx > -1 && idx < this.routes.length) {
this.removePin(this.routes[idx]);
OpenLayers.Util.removeItem(this.routes, this.routes[idx]);
}
},
/**
* 모든 경유지 제거
* @method removeAllRoutePoint
*/
removeAllRoutePoint: function() {
var r = this.routes.pop();
while (r) {
this.removePin(r);
r = this.routes.pop();
}
}
});
/**
* 경유지 최대 개수
* @property ROUTE_MAX_SIZE
* @type {Integer}
* @static
*/
CHZERO.Control.Cns.ROUTE_MAX_SIZE = 3;
/**
* CNS TYPE - 최적 모드
* @property BEST_TYPE
* @type {String}
* @static
*/
CHZERO.Control.Cns.BEST_TYPE = '0';
/**
* CNS TYPE - 최단 모드
* @property SHORTEST_TYPE
* @type {String}
* @static
*/
CHZERO.Control.Cns.SHORTEST_TYPE = '1';
/**
* CNS TYPE - 고속 모드
* @property HIGHWAY_TYPE
* @type {String}
* @static
*/
CHZERO.Control.Cns.HIGHWAY_TYPE = '2';
/**
* CNS TYPE - 무료 모드
* @property FREE_TYPE
* @type {String}
* @static
*/
CHZERO.Control.Cns.FREE_TYPE = '3';