* 풀 소스 코드 맨 아래에 있습니다.


# 도움 받은 Shp 파일

http://www.gisdeveloper.co.kr/?p=2332 

 

대한민국 최신 행정구역(SHP) 다운로드 – GIS Developer

 

www.gisdeveloper.co.kr

# vworld 참고 부분

https://www.vworld.kr/dev/v4dv_opnws3dmap2exam_s002.do?exaIde=EXAID_00000000000121&tabMenu=m1&searchKeyword= 

 

 

공간정보 오픈플랫폼 오픈API

웹지엘 3D지도 API 2.0 레퍼런스 웹지엘 3D지도 API 2.0 레퍼런스를 제공합니다.

www.vworld.kr

 

 

공간정보 오픈플랫폼 오픈API

웹지엘 3D지도 API 2.0 레퍼런스 웹지엘 3D지도 API 2.0 레퍼런스를 제공합니다.

www.vworld.kr


 

# shp 파일을 올리기 위한 과정

-  vworld 3d에 shp파일을 올리기 위해서 shp 파일을 QGIS 프로그램을 사용하여 geojson으로 변환합니다.

 

 

- QGIS 에서 shp 파일을 geojosn 파일로 변환

- geojson 파일을 미리 생성합니다.

- SIG_202101 파일을 sig.json 파일 생성


1. HTML 코드

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>WebGL_2.0_MapController</title>
    <script type="text/javascript"
            src="https://map.vworld.kr/js/webglMapInit.js.do?version=2.0&apiKey=767B7ADF-10BA-3D86-AB7E-02816B5B92E9"></script>
</head>
<div id="vmap" style="width:100%;height:50vh;left:0px;top:0px"></div>
<div id="features"></div>
<script type="text/javascript">

2. vworld 3d 맵 생성 부분

// 맵 생성 
    var mapOptions = new vw.MapOptions( 
        vw.BasemapType.GRAPHIC,
        "",
        vw.DensityType.FULL,
        vw.DensityType.BASIC,
        false,
        new vw.CameraPosition(
            new vw.CoordZ(126.9753042,37.5599416, 5000),
            new vw.Direction(-90, 0, 0)
        ),
        new vw.CameraPosition(
            new vw.CoordZ(126.9753042,37.5599416, 5000),
            new vw.Direction(0, -60, 0)
        )
    );
    map = new vw.Map("vmap", mapOptions);

    // 맵 생성 후, 콜백
    vw.ws3dInitCallBack = function () {
        // geojson 표현 스타일
        let opt = [
            {material: new vw.Color(0, 0, 154).ws3dColor.withAlpha(0.3)}, // 첫번째 shp 적용 스타일
            {material: new vw.Color(102, 178, 255).ws3dColor.withAlpha(0.2)},
            {material: new vw.Color(153, 0, 0).ws3dColor.withAlpha(0.2)},
            {material: new vw.Color(255, 255, 51).ws3dColor.withAlpha(0.2)},
            {material: new vw.Color(102, 0, 204).ws3dColor.withAlpha(0.2)},
        ];

        // 불러올 geojson 
        [
            "./file/sig.json",
        ].forEach((v, i) => {
            geojson(v, opt[i] !== void 0 ? opt[i] : void 0);
        });
    }

3. geojson 생성 부분

  /**
     * @param url - 파일 경로
     * @param opt - geojson 표현 방법
     */
    function geojson(url, opt) {

        // parser 설명.
        var parser = new vw.GMLParser();
        // 아이디 지정. --> parser에 지정이 되면, Feature객체에게도 상속 "sample-0,1,..." 형태로 아이디가 부여됩니다.
        parser.setId(url);
        //var featureInfos = parser.readTemp(vw.GMLParserType.GEOJSON, url, "EPSG:900913");
        // data 읽기. parser.read( 데이터타입, 데이터경로, 데이터좌표계)
        // 전달되는 좌표계를 의미하며, 이 좌표를 웹지엘에서는 EPSG:4326으로 변환하여 사용합니다.
        // 데이터타입. vw.GMLParserType { GEOJSON, GML1, GML2, GML2 }
        var featureInfos = parser.read(vw.GMLParserType.GEOJSON, url, "EPSG:4326");

        console.log("featureInfos :", featureInfos);
        var option = {
            isTerrain: true,      // 지형 따라 출력시 true, 지면에서 위로 출력시 false
            width: 10,         // 선의 경우 크기지정.
            material: new vw.Color(Math.floor(Math.random() * 255), Math.floor(Math.random() * 255), Math.floor(Math.random() * 255)).ws3dColor.withAlpha(0.1),  // RGBA A값만 255이하로 주면 투명 또는 withAlpha(1.0~0.1)로 설정.
            // material: new vw.Color(0, 0, 128).ws3dColor.withAlpha(1),  // RGBA A값만 255이하로 주면 투명 또는 withAlpha(1.0~0.1)로 설정.
            outline: true,         // 아웃라인지정시 true, 아웃라인 미지정 false 지형 결합 시 라인이 생성되지않음
            outlineWidth: 5,       // 아웃라인 너비.
            outlineColor: vw.Color.YELLOW.ws3dColor,       // 아웃라인 색상.
            height: 1.0         // 높이 지정값 meter.
        };
        var options = {...option, ...opt};

        // 출력 색상등 지정.
        featureInfos.setOption(options);

        const promise = new Promise((resolve, reject) => {
            featureInfos.makeCoords();
            resolve('promise');
        });

        promise.then((value) => {
            // console.log(value);
            var result = "";
            featureInfos.objCollection.collectionProp.forEach(function (i) { // objCollection.collectionProp 객체의 속성 값을 가지고 있음
                // console.log(i);
                result += i.properties.SIG_KOR_NM + " "
                $("#features").html(result);
            })
        });

        var selFeature = null;
        // 이벤트
        var featureEventHandler = function (windowPosition, ecefPosition, cartographic, featureInfo) {
            //ws3d.viewer.map.clearAllHighlightedFeatures();
            //featureInfo 가 존재 -> 3D 객체 클릭
            //onsole.log("featureInfo :" , windowPosition, ecefPosition, cartographic, featureInfo);
            if (featureInfo) {
                var feature = featureInfos.getById(featureInfo.groupId);
                // console.log("after feature :", featureInfos.objCollection);
                console.log("feature :", feature);
                // 그래픽객체 미출력
                // feature.hide();
                // FeatureInfo 객체 삭제1.
                //featureInfos.removeById(feature.id);
                // FeatureInfo 객체 삭제2.
                // featureInfos.removeByObj(feature);
                // feature 정보를 가지고 있는 properties
                console.log("feature properties:" , feature.getProperties());
                // console.log("after feature :", featureInfos.objCollection);

                // 이전 선택 객체 보여주기
                if(selFeature) {
                    selFeature.show();
                }
                // 객체 변경 후, 숨기기
                selFeature = feature;
                selFeature.hide();
            }
        };
        // 이벤트 설정.
        featureInfos.addEventListener(featureEventHandler);
        // 출력.
        featureInfos.show();
    }

4. 결과화면

 - geojson 표현된 부분 클릭 시, hide() 및 정보를 console를 통해 확인 가능합니다.


더보기
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>WebGL_2.0_MapController</title>
    <script type="text/javascript"
            src="https://map.vworld.kr/js/webglMapInit.js.do?version=2.0&apiKey=767B7ADF-10BA-3D86-AB7E-02816B5B92E9"></script>
</head>
<div id="vmap" style="width:100%;height:50vh;left:0px;top:0px"></div>
<div id="features"></div>

<script type="text/javascript">
    // 맵 생성
    var mapOptions = new vw.MapOptions(
        vw.BasemapType.GRAPHIC,
        "",
        vw.DensityType.FULL,
        vw.DensityType.BASIC,
        false,
        new vw.CameraPosition(
            new vw.CoordZ(126.9753042,37.5599416, 5000),
            new vw.Direction(-90, 0, 0)
        ),
        new vw.CameraPosition(
            new vw.CoordZ(126.9753042,37.5599416, 5000),
            new vw.Direction(0, -60, 0)
        )
    );
    map = new vw.Map("vmap", mapOptions);

    // 맵 생성 후, 콜백
    vw.ws3dInitCallBack = function () {
        // geojson 표현 스타일
        let opt = [
            {material: new vw.Color(0, 0, 154).ws3dColor.withAlpha(0.3)}, // 첫번째 shp 적용 스타일
            {material: new vw.Color(102, 178, 255).ws3dColor.withAlpha(0.2)},
            {material: new vw.Color(153, 0, 0).ws3dColor.withAlpha(0.2)},
            {material: new vw.Color(255, 255, 51).ws3dColor.withAlpha(0.2)},
            {material: new vw.Color(102, 0, 204).ws3dColor.withAlpha(0.2)},
        ];

        // 불러올 geojson
        [
            "./file/sig.json",
        ].forEach((v, i) => {
            geojson(v, opt[i] !== void 0 ? opt[i] : void 0);
        });
    }

    /**
     * @param url - 파일 경로
     * @param opt - geojson 표현 방법
     */
    function geojson(url, opt) {

        // parser 설명.
        var parser = new vw.GMLParser();
        // 아이디 지정. --> parser에 지정이 되면, Feature객체에게도 상속 "sample-0,1,..." 형태로 아이디가 부여됩니다.
        parser.setId(url);
        //var featureInfos = parser.readTemp(vw.GMLParserType.GEOJSON, url, "EPSG:900913");
        // data 읽기. parser.read( 데이터타입, 데이터경로, 데이터좌표계)
        // 전달되는 좌표계를 의미하며, 이 좌표를 웹지엘에서는 EPSG:4326으로 변환하여 사용합니다.
        // 데이터타입. vw.GMLParserType { GEOJSON, GML1, GML2, GML2 }
        var featureInfos = parser.read(vw.GMLParserType.GEOJSON, url, "EPSG:4326");

        console.log("featureInfos :", featureInfos);
        var option = {
            isTerrain: true,      // 지형 따라 출력시 true, 지면에서 위로 출력시 false
            width: 10,         // 선의 경우 크기지정.
            material: new vw.Color(Math.floor(Math.random() * 255), Math.floor(Math.random() * 255), Math.floor(Math.random() * 255)).ws3dColor.withAlpha(0.1),  // RGBA A값만 255이하로 주면 투명 또는 withAlpha(1.0~0.1)로 설정.
            // material: new vw.Color(0, 0, 128).ws3dColor.withAlpha(1),  // RGBA A값만 255이하로 주면 투명 또는 withAlpha(1.0~0.1)로 설정.
            outline: true,         // 아웃라인지정시 true, 아웃라인 미지정 false 지형 결합 시 라인이 생성되지않음
            outlineWidth: 5,       // 아웃라인 너비.
            outlineColor: vw.Color.YELLOW.ws3dColor,       // 아웃라인 색상.
            height: 1.0         // 높이 지정값 meter.
        };
        var options = {...option, ...opt};

        // 출력 색상등 지정.
        featureInfos.setOption(options);

        const promise = new Promise((resolve, reject) => {
            featureInfos.makeCoords();
            resolve('promise');
        });

        promise.then((value) => {
            // console.log(value);
            var result = "";
            featureInfos.objCollection.collectionProp.forEach(function (i) { // objCollection.collectionProp 객체의 속성 값을 가지고 있음
                // console.log(i);
                result += i.properties.SIG_KOR_NM + " "
                $("#features").html(result);
            })
        });

        var selFeature = null;
        // 이벤트
        var featureEventHandler = function (windowPosition, ecefPosition, cartographic, featureInfo) {
            //ws3d.viewer.map.clearAllHighlightedFeatures();
            //featureInfo 가 존재 -> 3D 객체 클릭
            //onsole.log("featureInfo :" , windowPosition, ecefPosition, cartographic, featureInfo);
            if (featureInfo) {
                var feature = featureInfos.getById(featureInfo.groupId);
                // console.log("after feature :", featureInfos.objCollection);
                console.log("feature :", feature);
                // 그래픽객체 미출력
                // feature.hide();
                // FeatureInfo 객체 삭제1.
                //featureInfos.removeById(feature.id);
                // FeatureInfo 객체 삭제2.
                // featureInfos.removeByObj(feature);
                // feature 정보를 가지고 있는 properties
                console.log("feature properties:" , feature.getProperties());
                // console.log("after feature :", featureInfos.objCollection);

                // 이전 선택 객체 보여주기
                if(selFeature) {
                    selFeature.show();
                }
                // 객체 변경 후, 숨기기
                selFeature = feature;
                selFeature.hide();
            }
        };
        // 이벤트 설정.
        featureInfos.addEventListener(featureEventHandler);
        // 출력.
        featureInfos.show();
    }

</script>
<body>

</body>
</html>
블로그 이미지

미나미나미

,

 

2022.02.24 - [[Spring]/springboot] - [SpringBoot] RestAPI 파일업로드 - 1

 

[SpringBoot] RestAPI 파일업로드 - 1

1. start.spring.io에서 스프링 프로젝트 생성하기 2. 파일 업로드 관련 properties 생성 spring: servlet: multipart: max-request-size: 500MB # request 요청 제한(defalut 10mb) max-file-size: 500MB # 파..

minaminaworld.tistory.com


1. 프로젝트 메인에서 업로드 폴더 생성 

   @Value("${uploadFolder}")
    private String uploadFolder;

    public static void main(String[] args) {
        SpringApplication.run(TistoryFileDownloadApplication.class, args);
    }

    @PostConstruct
    public void createUploadFolder() {
        Path upload = Paths.get(uploadFolder);
        try {
            if (!Files.exists(upload)) {
                Files.createDirectory(upload);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2. 파일 저장 서비스 코드 작성

@Service
public class FileService {

    @Value("${uploadFolder}")
    private String uploadFolder;

    public void save(MultipartFile file) {
        Path upload = Paths.get(uploadFolder);
        try {
            Files.copy(file.getInputStream(), upload.resolve(file.getOriginalFilename()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. Postman 테스트 결과 

 

블로그 이미지

미나미나미

,

1. start.spring.io에서 스프링 프로젝트 생성하기


 

2. 파일 업로드 관련 properties 생성

spring:
  servlet:
    multipart:
      max-request-size: 500MB # request 요청 제한(defalut 10mb)
      max-file-size: 500MB # 파일 크기 업로드 데한 (defalut 10mb)

uploadFoloder: upload

3. 파일 RestController 생성 

@PostMapping("/upload")
public ResponseEntity upload(
	@RequestParam("files") MultipartFile[] files // 파일 받기
) {
	// 1. response 객체 생성
    HashMap<String, Object> resultMap = new HashMap<>();
    HashMap<String, Object> responseData = new HashMap<>();
    
    // 2. 받은 파일 데이터 확인
    List<HashMap<String, Object>> fileNames = new ArrayList<>();
    	Arrays.stream(files).forEach(f -> {
    	HashMap<String, Object> map = new HashMap<>();
	    System.out.println("f.getOriginalFilename() = " + f.getOriginalFilename());
    	map.put("fileName", f.getOriginalFilename());
    	map.put("fileSize", f.getSize());
    
        fileNames.add(map);
    });
    
    // 3. response 하기
    responseData.put("files", fileNames);
    resultMap.put("response", responseData);
    return ResponseEntity.ok().body(resultMap);
}

4. Postman으로 테스트 하기  

   파일을 서버에서 전달 테스트

블로그 이미지

미나미나미

,