feat: 광산 클릭 시 광산 정보보여지도록 수정
parent
b8c26b33ac
commit
b422380f16
|
|
@ -11,6 +11,13 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
|
@ -158,4 +165,113 @@ public class MapMainController {
|
|||
|
||||
return "map/left/include/comMove";
|
||||
}
|
||||
|
||||
/**
|
||||
* 광산 정보 WFS 프록시 (CORS 해결용)
|
||||
* @param request
|
||||
* @param response
|
||||
* @param params
|
||||
* @throws Exception
|
||||
*/
|
||||
@RequestMapping(value = "/map/getMineWFS.do")
|
||||
public void getMineWFS(HttpServletRequest request, HttpServletResponse response, @RequestParam HashMap<String, Object> params) throws Exception {
|
||||
|
||||
// 1. 공공데이터포털 서비스 키 (Decoding 된 키 사용)
|
||||
String serviceKey = "L1z0zEpxNLB0Sqwv97WAIyL1lB+shPemDLNaG9hy9g3BzbkXRVG2/aSTZ7PiAAivgaCYn9p1tLmq2keiC4yFZA==";
|
||||
|
||||
// 2. 요청 파라미터 받기 (OpenLayers에서 bbox를 보냄)
|
||||
String bbox = request.getParameter("bbox");
|
||||
|
||||
// 3. API URL 생성
|
||||
StringBuilder urlBuilder = new StringBuilder("https://apis.data.go.kr/1480523/GeologicalService/getMineWFS");
|
||||
urlBuilder.append("?" + URLEncoder.encode("ServiceKey", "UTF-8") + "=" + URLEncoder.encode(serviceKey, "UTF-8"));
|
||||
urlBuilder.append("&" + URLEncoder.encode("srsName", "UTF-8") + "=" + URLEncoder.encode("EPSG:3857", "UTF-8"));
|
||||
urlBuilder.append("&" + URLEncoder.encode("maxFeatures", "UTF-8") + "=" + URLEncoder.encode("100", "UTF-8"));
|
||||
urlBuilder.append("&" + URLEncoder.encode("resultType", "UTF-8") + "=" + URLEncoder.encode("results", "UTF-8"));
|
||||
|
||||
// 버전을 1.0.0으로 명시 (GML 2 포맷 요청)
|
||||
urlBuilder.append("&" + URLEncoder.encode("version", "UTF-8") + "=" + URLEncoder.encode("1.0.0", "UTF-8"));
|
||||
|
||||
// bbox가 있을 경우에만 추가 (OpenLayers Strategy.BBOX가 자동으로 보냄)
|
||||
if (bbox != null && !bbox.isEmpty()) {
|
||||
urlBuilder.append("&" + URLEncoder.encode("bbox", "UTF-8") + "=" + URLEncoder.encode(bbox, "UTF-8"));
|
||||
}
|
||||
|
||||
// 4. HTTP 연결 설정
|
||||
URL url = new URL(urlBuilder.toString());
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setRequestProperty("Content-type", "application/xml"); // WFS는 XML 응답
|
||||
|
||||
// 5. 응답 코드 확인 및 스트림 연결
|
||||
// 응답을 읽어서 브라우저로 바로 쏘아줍니다 (Pass-through)
|
||||
response.setContentType("text/xml;charset=UTF-8"); // 브라우저에게 XML임을 알림
|
||||
|
||||
BufferedReader rd;
|
||||
if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
|
||||
rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
|
||||
} else {
|
||||
rd = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "UTF-8"));
|
||||
}
|
||||
|
||||
// 6. 데이터 읽기 및 쓰기
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = rd.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
rd.close();
|
||||
conn.disconnect();
|
||||
|
||||
// 클라이언트로 응답 전송
|
||||
response.getWriter().write(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 광산 상세 정보 조회 (getInfo API 프록시)
|
||||
* @param request
|
||||
* @param response
|
||||
* @param params
|
||||
* @throws Exception
|
||||
*/
|
||||
@RequestMapping(value = "/map/getMineInfo.do")
|
||||
public void getMineInfo(HttpServletRequest request, HttpServletResponse response, @RequestParam HashMap<String, Object> params) throws Exception {
|
||||
|
||||
// 1. 서비스 키 & 파라미터 설정
|
||||
String serviceKey = "L1z0zEpxNLB0Sqwv97WAIyL1lB+shPemDLNaG9hy9g3BzbkXRVG2/aSTZ7PiAAivgaCYn, 9p1tLmq2keiC4yFZA==";
|
||||
String mgtNo = request.getParameter("mgtNo");
|
||||
|
||||
// 2. API URL 생성 (JSON 요청)
|
||||
StringBuilder urlBuilder = new StringBuilder("https://apis.data.go.kr/1480523/GeologicalService/getMine");
|
||||
urlBuilder.append("?" + URLEncoder.encode("ServiceKey", "UTF-8") + "=" + URLEncoder.encode(serviceKey, "UTF-8"));
|
||||
urlBuilder.append("&" + URLEncoder.encode("mgtNo", "UTF-8") + "=" + URLEncoder.encode(mgtNo, "UTF-8"));
|
||||
urlBuilder.append("&" + URLEncoder.encode("type", "UTF-8") + "=" + URLEncoder.encode("json", "UTF-8")); // JSON 응답 요청
|
||||
|
||||
// 3. API 호출
|
||||
URL url = new URL(urlBuilder.toString());
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setRequestProperty("Content-type", "application/json");
|
||||
|
||||
// 4. 응답 전달
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
|
||||
BufferedReader rd;
|
||||
if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
|
||||
rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
|
||||
} else {
|
||||
rd = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "UTF-8"));
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = rd.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
rd.close();
|
||||
conn.disconnect();
|
||||
|
||||
// 클라이언트로 JSON 문자열 전송
|
||||
response.getWriter().write(sb.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,6 +356,7 @@ var HOLE_LAYER_M; // 시추공 레이어2
|
|||
var GEOLOGY_LAYER; // 지질도/광물 레이어
|
||||
var MINERAL_LAYER; // 광물 레이어
|
||||
var MINE_LAYER; // 광산 레이어
|
||||
var CTL_SELECT_MINE; // 광산 선택
|
||||
var WELL_LAYER; // 관정 레이어
|
||||
var STEEP_SLOPE_LAYER; // 급경사지 레이어
|
||||
var CTL_SELECT_SLOPE; // 급경사지 선택
|
||||
|
|
@ -876,49 +877,236 @@ function initApp(param){
|
|||
transparent: true
|
||||
};
|
||||
|
||||
// ▼▼▼ 광산정보 (WFS Custom Parsing & Selection) ▼▼▼
|
||||
var mineStyle = new OpenLayers.Style({
|
||||
pointRadius: 6,
|
||||
fillColor: "#ff0000",
|
||||
strokeColor: "#ffffff",
|
||||
strokeWidth: 1,
|
||||
graphicName: "square",
|
||||
fillOpacity: 0.7,
|
||||
cursor: "pointer"
|
||||
});
|
||||
|
||||
MINE_LAYER = new OpenLayers.Layer.Grid(
|
||||
"Mine Map",
|
||||
mineBaseUrl, // Base URL
|
||||
mineParams, // 정적 파라미터
|
||||
{
|
||||
isBaseLayer: false,
|
||||
visibility: false,
|
||||
opacity: 0.7,
|
||||
singleTile: true, // 단일 타일로 요청
|
||||
|
||||
/**
|
||||
* getURL 함수를 재정의(override)하여
|
||||
* 원하는 URL 형식을 직접 만듭니다.
|
||||
*/
|
||||
getURL: function(bounds) {
|
||||
// 1. 맵의 현재 영역(bounds)을 BBOX 문자열로 변환
|
||||
var bbox = bounds.toBBOX();
|
||||
|
||||
// 2. 맵의 현재 픽셀 크기(width, height)
|
||||
var size = this.map.getSize();
|
||||
|
||||
// 3. 기본 URL (mineBaseUrl)
|
||||
var url = this.url;
|
||||
|
||||
// 4. 정적 파라미터 (ServiceKey, srs, format 등) 복사
|
||||
// OpenLayers.Util.extend는 객체를 복사합니다.
|
||||
var params = OpenLayers.Util.extend({}, this.params);
|
||||
|
||||
// 5. 동적 파라미터 (bbox, width, height) 추가
|
||||
params.bbox = bbox;
|
||||
params.width = size.w;
|
||||
params.height = size.h;
|
||||
|
||||
// 6. 모든 파라미터를 URL에 조합하여 최종 요청 URL 반환
|
||||
// OpenLayers.Util.urlAppend가 ? 와 & 를 알아서 처리해줍니다.
|
||||
return OpenLayers.Util.urlAppend(url, OpenLayers.Util.getParameterString(params));
|
||||
MINE_LAYER = new OpenLayers.Layer.Vector("Mine Map", {
|
||||
strategies: [new OpenLayers.Strategy.BBOX({
|
||||
ratio: 1.1,
|
||||
resFactor: 1
|
||||
})],
|
||||
protocol: new OpenLayers.Protocol.HTTP({
|
||||
url: "/map/getMineWFS.do",
|
||||
headers: { "Content-Type": "plain/text" },
|
||||
params: {},
|
||||
format: new OpenLayers.Format.XML({
|
||||
read: function(data) {
|
||||
if (typeof data == "string") {
|
||||
data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
|
||||
}
|
||||
|
||||
var features = [];
|
||||
var elements = data.getElementsByTagName("*");
|
||||
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var el = elements[i];
|
||||
var tagName = el.localName || el.nodeName.split(":").pop();
|
||||
|
||||
if (tagName === "MINE_POINT") {
|
||||
try {
|
||||
// 좌표 추출
|
||||
var posNodes = el.getElementsByTagName("pos");
|
||||
if(posNodes.length === 0) posNodes = el.getElementsByTagName("gml:pos");
|
||||
|
||||
if (posNodes.length > 0) {
|
||||
var posText = OpenLayers.String.trim(posNodes[0].textContent || posNodes[0].text);
|
||||
var coords = posText.split(/\s+/);
|
||||
var x = parseFloat(coords[0]);
|
||||
var y = parseFloat(coords[1]);
|
||||
|
||||
// 속성(MGTNO) 추출 로직 활성화
|
||||
var attributes = {};
|
||||
|
||||
// 태그명이 MGTNO 또는 openAPI:MGTNO 인 것을 찾음
|
||||
var mgtNodes = el.getElementsByTagName("MGTNO");
|
||||
if(mgtNodes.length === 0) mgtNodes = el.getElementsByTagName("openAPI:MGTNO");
|
||||
|
||||
if(mgtNodes.length > 0) {
|
||||
attributes.MGTNO = mgtNodes[0].textContent || mgtNodes[0].text;
|
||||
} else {
|
||||
attributes.MGTNO = "정보없음";
|
||||
}
|
||||
|
||||
|
||||
var objectIdNodes = el.getElementsByTagName("OBJECTID");
|
||||
if(objectIdNodes.length === 0) objectIdNodes = el.getElementsByTagName("openAPI:OBJECTID");
|
||||
|
||||
if(objectIdNodes.length > 0) {
|
||||
attributes.OBJECTID = objectIdNodes[0].textContent || objectIdNodes[0].text;
|
||||
} else {
|
||||
attributes.OBJECTID = "정보없음";
|
||||
}
|
||||
|
||||
var geometry = new OpenLayers.Geometry.Point(x, y);
|
||||
var feature = new OpenLayers.Feature.Vector(geometry, attributes);
|
||||
features.push(feature);
|
||||
}
|
||||
} catch(err) {
|
||||
console.error("광산 데이터 파싱 에러:", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
return features;
|
||||
}
|
||||
}),
|
||||
readWithRequest: true
|
||||
}),
|
||||
styleMap: new OpenLayers.StyleMap({
|
||||
"default": mineStyle,
|
||||
"select": { // 선택되었을 때 스타일 (노란색)
|
||||
pointRadius: 8,
|
||||
fillColor: "#ffff00",
|
||||
strokeColor: "#ff0000",
|
||||
fillOpacity: 1
|
||||
}
|
||||
}
|
||||
);
|
||||
}),
|
||||
visibility: false
|
||||
});
|
||||
BASE_MAP.addLayer(MINE_LAYER);
|
||||
// ▲▲▲ 광산정보 ▲▲▲
|
||||
|
||||
|
||||
// 광산 선택(클릭) 컨트롤 생성
|
||||
CTL_SELECT_MINE = new OpenLayers.Control.SelectFeature(MINE_LAYER, {
|
||||
clickout: true, toggle: true,
|
||||
multiple: false, hover: false,
|
||||
onSelect: function(feature) {
|
||||
var mgtNo = feature.attributes.MGTNO;
|
||||
var objectId = feature.attributes.OBJECTID;
|
||||
|
||||
// 관리번호가 없는 경우 처리
|
||||
if (!mgtNo || mgtNo === "정보없음") {
|
||||
alert("관리번호 정보가 없습니다.");
|
||||
this.unselect(feature);
|
||||
return;
|
||||
}
|
||||
|
||||
// 백엔드 프록시('/map/getMineInfo.do')를 통해 API 호출
|
||||
$.ajax({
|
||||
url: "/map/getMineInfo.do",
|
||||
type: "GET",
|
||||
data: { mgtNo: mgtNo },
|
||||
dataType: "json", // JSON 문자열을 그대로 받기 위해 text 사용
|
||||
success: function(data) {
|
||||
|
||||
//mgtNo가 같아도 다른 광산이 많이 존재한다... 필요시 하드 코딩을 하기 위해, 아래 전국 mineList를 JSON으로 정리해서 특정 광산과 연결하도록 구현하였다.
|
||||
var mineList = {
|
||||
"ME2010A006": [
|
||||
1
|
||||
],
|
||||
"ND2009A002": [
|
||||
2 // 2 일광광산 부산광역시 기장군 일광면 원리 190-1 일원
|
||||
],
|
||||
"ME2015A013": [
|
||||
3,
|
||||
4
|
||||
],
|
||||
"ME2009E003": [
|
||||
5
|
||||
],
|
||||
"WJ2016E001": [
|
||||
6,
|
||||
7
|
||||
],
|
||||
"HG2008E012": [
|
||||
8,
|
||||
9,
|
||||
10
|
||||
],
|
||||
"JJ2005E006": [
|
||||
11,
|
||||
12
|
||||
],
|
||||
"ME2010E001": [
|
||||
20,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19, // 19 일광광산 부산광역시 기장군 일광면 원리
|
||||
13, // 13 동래군 기장면
|
||||
24
|
||||
],
|
||||
"ND2014E002": [
|
||||
21,
|
||||
22,
|
||||
23
|
||||
],
|
||||
"ND2016B003": [
|
||||
25 // (가)궁근정 울산 울주군
|
||||
],
|
||||
"WJ2005E011": [
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29
|
||||
],
|
||||
"HG2017B004": [
|
||||
30
|
||||
],
|
||||
"HG2022G001": [
|
||||
32 // 광장 서울특별시 강동구 암사동 100-3
|
||||
],
|
||||
"ND2022E003": [
|
||||
31 // (가)궁근정 울산광역시 울주군 상북면 궁근정리
|
||||
]
|
||||
};
|
||||
for( idx in mineList[data.response.body.mgtno] ) {
|
||||
if( Number(mineList[data.response.body.mgtno][idx]) === Number(objectId) ) {
|
||||
item = data.response.body.mines[idx];
|
||||
console.log( '%o', item);
|
||||
objectId = Number(objectId);
|
||||
var contents = '';
|
||||
if( item.mineAdres ) {
|
||||
contents += '주소: ' + item.mineAdres + '\n';
|
||||
}
|
||||
if( item.mineKnd ) {
|
||||
contents += '광물: ' + item.mineKnd + '\n';
|
||||
}
|
||||
if( item.mineNm ) {
|
||||
contents += '광산 식별명: ' + item.mineNm + '\n';
|
||||
}
|
||||
|
||||
if( item.mineTy ) {
|
||||
contents += '기타: ' + item.mineTy + '\n';
|
||||
}
|
||||
|
||||
if( objectId ) {
|
||||
contents += '식별 번호: ' + objectId + '\n';
|
||||
}
|
||||
var validationTailler = ' 미확인';
|
||||
if( objectId === 31 || objectId === 32 || objectId === 25 ||
|
||||
objectId === 2 ||
|
||||
objectId === 13 ||
|
||||
objectId === 19
|
||||
) {
|
||||
validationTailler = ' 검증됨';
|
||||
}
|
||||
console.log( contents + validationTailler );
|
||||
alert( contents );
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error("API 호출 에러:", error);
|
||||
alert("상세 정보를 가져오는데 실패했습니다.");
|
||||
},
|
||||
complete: function() {
|
||||
// 알림창 닫은 후 선택 상태 해제 (다시 클릭 가능하도록)
|
||||
CTL_SELECT_MINE.unselect(feature);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
BASE_MAP.addControl(CTL_SELECT_MINE);
|
||||
// ▲▲▲ 광산정보 (WFS Custom Parsing & Selection) ▲▲▲
|
||||
|
||||
|
||||
// ▼▼▼ 관정정보 ▼▼▼
|
||||
|
|
@ -3833,6 +4021,7 @@ function initControl(){
|
|||
HOLE_SELECT2.removeAllFeatures();
|
||||
CTL_SELECT.deactivate();
|
||||
if(CTL_SELECT_SLOPE) CTL_SELECT_SLOPE.deactivate(); // 급경사지 선택 비활성화
|
||||
if(CTL_SELECT_MINE) CTL_SELECT_MINE.deactivate(); // 광산 선택 비활성화
|
||||
CTL_SELECT_PROJECT.deactivate();
|
||||
CTL_SELECT_JIBAN.deactivate();
|
||||
CTL_TOOLTIP.activate();
|
||||
|
|
@ -5423,41 +5612,69 @@ function geologyMineral() {
|
|||
}
|
||||
|
||||
function geologyMine() {
|
||||
initControl(); // 다른 컨트롤 상태 초기화
|
||||
|
||||
// MINE_LAYER가 정상적으로 생성되었는지 확인
|
||||
initControl(); // 다른 컨트롤 초기화
|
||||
|
||||
if (!MINE_LAYER) {
|
||||
console.error("광산 레이어가 초기화되지 않았습니다.");
|
||||
alert("오류: 광산 레이어가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 현재 레이어의 표시 상태를 가져옵니다.
|
||||
var isVisible = MINE_LAYER.getVisibility();
|
||||
|
||||
if (isVisible ) {
|
||||
// 레이어가 현재 보이고 있다면, 숨깁니다.
|
||||
MINE_LAYER.setVisibility(false);
|
||||
CTL_INFO.setText("지질 Off");
|
||||
CTL_INFO.deactivate(); // 정보창도 비활성화
|
||||
if (isVisible) {
|
||||
// [OFF] 기능 끄기
|
||||
MINE_LAYER.setVisibility(false);
|
||||
if(CTL_SELECT_MINE) CTL_SELECT_MINE.deactivate();
|
||||
|
||||
removeGeologyLegend(); // 끌 때 범례도 닫습니다.
|
||||
CTL_INFO.setText("지질 Off");
|
||||
CTL_INFO.deactivate();
|
||||
removeGeologyLegend();
|
||||
console.log("[광산] 레이어 OFF");
|
||||
|
||||
} else {
|
||||
|
||||
// 레이어를 보이게 설정하고 강제로 다시 그립니다.
|
||||
// [ON] 기능 켜기
|
||||
MINE_LAYER.setVisibility(true);
|
||||
MINE_LAYER.redraw(true);
|
||||
|
||||
// CTL_INFO의 infoDiv가 내부 요소를 absolute 포지셔닝할 수 있도록 'relative'로 설정
|
||||
$(CTL_INFO.infoDiv).css("position", "relative");
|
||||
|
||||
// CTL_INFO 텍스트 설정 시 버튼 HTML을 함께 삽입
|
||||
// 레이어 Z-Index를 최상위로 설정
|
||||
// 다른 레이어(WMS, 툴팁 등)보다 무조건 위에 오도록 값을 높게 설정합니다.
|
||||
var maxZ = 0;
|
||||
for(var i=0; i<BASE_MAP.layers.length; i++) {
|
||||
if(BASE_MAP.layers[i].getZIndex() > maxZ) {
|
||||
maxZ = BASE_MAP.layers[i].getZIndex();
|
||||
}
|
||||
}
|
||||
MINE_LAYER.setZIndex(maxZ + 500); // 가장 높은 값보다 500 더 높게
|
||||
MINE_LAYER.redraw(true);
|
||||
|
||||
// 선택 컨트롤 재활성화 및 로그 출력
|
||||
if(CTL_SELECT_MINE) {
|
||||
CTL_SELECT_MINE.deactivate();
|
||||
var activated = CTL_SELECT_MINE.activate();
|
||||
|
||||
// 현재 로드된 피처 개수 확인
|
||||
var featureCount = MINE_LAYER.features.length;
|
||||
console.log("[광산] 컨트롤 활성화 성공여부: " + activated);
|
||||
console.log("[광산] 현재 지도에 표시된 광산 개수: " + featureCount);
|
||||
|
||||
if(featureCount > 0) {
|
||||
console.log("[광산] 첫번째 광산 속성 예시:", MINE_LAYER.features[0].attributes);
|
||||
}
|
||||
|
||||
} else {
|
||||
console.error("[광산] CTL_SELECT_MINE 컨트롤이 없습니다! initApp에서 생성되었는지 확인하세요.");
|
||||
alert("오류: 광산 선택 컨트롤이 생성되지 않았습니다.");
|
||||
}
|
||||
|
||||
|
||||
$(CTL_INFO.infoDiv).css("position", "relative");
|
||||
CTL_INFO.setText("광산 On");
|
||||
CTL_INFO.activate();
|
||||
$("#CTL_INFO").css("bottom", "65px");
|
||||
$("#CTL_INFO").css("left", "20px");
|
||||
|
||||
alert('광산은 공개된 데이터가 많지 않습니다. 빨간색 사각형으로 표시됩니다.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue