# Java와 PostgreSQL을 통한 파일을 집어 넣기 전 준비 사항

 

1. postgreSQL JDBC Jar 추가하기 (https://jdbc.postgresql.org/download.html)

 

PostgreSQL JDBC Download

Download About Binary JAR file downloads of the JDBC driver are available here and the current version with Maven Repository. Because Java is platform neutral, it is a simple process of just downloading the appropriate JAR file and dropping it into your cl

jdbc.postgresql.org

2. PostgreSQL 테이블 생성

-- Drop table

-- DROP TABLE public.img_test;

CREATE TABLE public.img_test (
	file_id int4 NOT NULL DEFAULT nextval('newtable_1_file_id_seq'::regclass),
	filename varchar NULL,
	filesize int8 NULL,
	file bytea NULL,
	inst_dt timestamp(0) NULL
);


# DB에 이미지 넣는 부분 소스 코드

 public void insertImg() {
        File file = new File("../TestFileDir/잔망루피 4월 달력_새싹.jpg");
        FileInputStream fis = null;

        String name = file.getName();
        System.out.println("name = " + name);

        String sql = "INSERT INTO public.img_test (filename, filesize, file, inst_dt) VALUES(?, ?, ?, ?);";
        Connection connection = null;
        PreparedStatement pstmt = null;

        try {
            fis = new FileInputStream(file); 

            connection = DriverManager.getConnection(connurl, user, password);
            pstmt = connection.prepareStatement(sql);

            pstmt.setString(1, file.getName());
            pstmt.setLong(2, file.length());
            pstmt.setBinaryStream(3, fis);
            pstmt.setTimestamp(4, Timestamp.valueOf(LocalDateTime.now()));

            pstmt.executeUpdate();
        } catch (SQLException | FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            try {
                pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

 

# 결과 화면


# 전체소스코드

더보기
package com.example.Img;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.file.Files;
import java.sql.*;
import java.time.LocalDateTime;

public class DatabaseSaveImg {

    private String connurl = "jdbc:postgresql://localhost:5432/DB명";
    private String user = "postgres";
    private String password = "postgres";

    public void connTest() {
        try {
            Class.forName("org.postgresql.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        try (Connection connection = DriverManager.getConnection(connurl, user, password);) {
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT VERSION() AS version");

            while (rs.next()) {
                String version = rs.getString("version");

                System.out.println(version);
            }
            rs.close();
            stmt.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void insertImg() {
        File file = new File("D:/SOURCE_CODE/2022/study/Database/insertImg/TestFileDir/잔망루피 4월 달력_새싹.jpg");
        FileInputStream fis = null;

        String name = file.getName();
        System.out.println("name = " + name);

        String sql = "INSERT INTO public.img_test (filename, filesize, file, inst_dt) VALUES(?, ?, ?, ?);";
        Connection connection = null;
        PreparedStatement pstmt = null;

        try {
            fis = new FileInputStream(file);

            connection = DriverManager.getConnection(connurl, user, password);
            pstmt = connection.prepareStatement(sql);

            pstmt.setString(1, file.getName());
            pstmt.setLong(2, file.length());
            pstmt.setBinaryStream(3, fis);
            pstmt.setTimestamp(4, Timestamp.valueOf(LocalDateTime.now()));

            pstmt.executeUpdate();
        } catch (SQLException | FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            try {
                pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

 

블로그 이미지

미나미나미

,

# OpenAPI 키 발행: https://www.data.go.kr/data/15012690/openapi.do 

# 서비스 키를 발급 받아야합니다.


# 프로젝트 구조

- ApiController.java

- RequestUtils.java 

 

1. 공공데이터에서 제공해주는 Java 버전의 API를 살짝 각색합니다.

  Year과 Month를 넣는 부분과 Json 형식으로 요청합니다.

2. Json으로 받은 데이터를 Hashmap으로 변환합니다.

# 1번과 2번 소스코드

private static String secretKey = "서비스키";
    
    public static Map<String, Object> holidayInfoAPI(String year, String month) throws IOException {
        StringBuilder urlBuilder = new StringBuilder("http://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService/getHoliDeInfo"); /*URL*/
        urlBuilder.append("?" + URLEncoder.encode("serviceKey", "UTF-8") + "=" + secretKey); /*Service Key*/
        urlBuilder.append("&" + URLEncoder.encode("pageNo", "UTF-8") + "=" + URLEncoder.encode("1", "UTF-8")); /*페이지번호*/
        urlBuilder.append("&" + URLEncoder.encode("numOfRows", "UTF-8") + "=" + URLEncoder.encode("10", "UTF-8")); /*한 페이지 결과 수*/
        urlBuilder.append("&" + URLEncoder.encode("solYear", "UTF-8") + "=" + URLEncoder.encode(year, "UTF-8")); /*연 */
        urlBuilder.append("&" + URLEncoder.encode("solMonth", "UTF-8") + "=" + URLEncoder.encode(month.length() == 1 ? "0" + month : month, "UTF-8")); /*월*/
        urlBuilder.append("&" + URLEncoder.encode("_type", "UTF-8") + "=" + URLEncoder.encode("json", "UTF-8")); /* json으로 요청 */

        URL url = new URL(urlBuilder.toString());
        System.out.println("요청URL = " + urlBuilder);

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-type", "application/json");
        System.out.println("Response code: " + conn.getResponseCode());

        BufferedReader rd;
        if (conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
            rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        } else {
            rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
        }
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = rd.readLine()) != null) {
            sb.append(line);
        }
        rd.close();
        conn.disconnect();
        // System.out.println(sb.toString());

        return string2Map(sb.toString());
    }

    /**
     * Json String을 Hashmap으로 반환
     *
     * @param json
     * @return
     */
    public static Map<String, Object> string2Map(String json) {
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> map = null;

        try {
            map = mapper.readValue(json, Map.class);
            System.out.println(map);

        } catch (IOException e) {
            e.printStackTrace();
        }

        return map;
    }

3. Controller 구성

* 공휴일 요청 후, 세 가지의 응답을 받게 됩니다.

  1. 공휴일이 없는 경우 

  2. 공휴일 하루 있는 경우

  3. 공휴일 이틀 이상인 경우

 

 

   @GetMapping("holidayInfoAPI")
    public ResponseEntity holidayInfoAPI(
            @PathParam("year") String year,
            @PathParam("month") String month
    ) {

        System.out.println("year = " + year);
        System.out.println("month = " + month);

        ArrayList<HashMap> responseHolidayArr = new ArrayList<>();

        try {
            Map<String, Object> holidayMap = RequestUtils.holidayInfoAPI(year, month);
            Map<String, Object> response = (Map<String, Object>) holidayMap.get("response");
            Map<String, Object> body = (Map<String, Object>) response.get("body");
            System.out.println("body = " + body);

            int totalCount = (int) body.get("totalCount");
            if (totalCount <= 0) {
                System.out.println("공휴일 없음");
            }
            if (totalCount == 1) {
                HashMap<String, Object> items = (HashMap<String, Object>) body.get("items");
                HashMap<String, Object> item = (HashMap<String, Object>) items.get("item");
                responseHolidayArr.add(item);
                System.out.println("item = " + item);
            }
            if (totalCount > 1) {
                HashMap<String, Object> items = (HashMap<String, Object>) body.get("items");
                ArrayList<HashMap<String, Object>> item = (ArrayList<HashMap<String, Object>>) items.get("item");
                for (HashMap<String, Object> itemMap : item) {
                    System.out.println("itemMap = " + itemMap);
                    responseHolidayArr.add(itemMap);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResponseEntity.ok().body(responseHolidayArr);
    }

4. 결과 화면

 

 

 

 

블로그 이미지

미나미나미

,

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


# 도움 받은 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으로 테스트 하기  

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

블로그 이미지

미나미나미

,

 

1. SQL 쿼리문 실행 

CREATE EXTENSION postgis;

 

2. 에러 발생 

 

 

 

 

3. 해결 방법 

   - C:\Program Files\PostgreSQL\10\bin\postgisgui 에서   "libeay32.dll" and "ssleay32.dll" 복사 

 

   - C:\Program Files\PostgreSQL\10\bin 에 붙여넣기

 

블로그 이미지

미나미나미

,

# 방향에 대한 이해 

위키피디아 이미지 : https://en.wikipedia.org/wiki/Aircraft_principal_axes

- vw.Direction(heading = yaw , tilt = pitch , roll)

   x 방향 : tilt(pitch) 

   y 방향 : yaw(heading)

   z 방향 : roll 

  # 단어 뜻을 따지면, 각각의 항목이 의미가 다르나, 단순히 방향의 관점에서 동일하다고 생각하고 작성함.

 

- vw.CoordZ( 경도, 위도 , 지면으로 부터 높이)


# 방향 전환 소스 코드 (아래 전체 소스 코드 확인)

        /**
         * 카메라 화면 이동하기  
         **/
        function moveCamera() {
            console.group('moveCamera');
            // 화면 select 문 값 읽어오기
            const e = document.getElementById("select");
            console.log(e);
            // 선택 값 확인 
            var value = parseInt(e.options[e.selectedIndex].value);
            var text = e.options[e.selectedIndex].text;
            console.log(value, text);

			// 현재 위치값 가져오기 
            const { direction, position } = map3d.getCurrentPosition();
            // 중심점 그리기, 필요하지 않으면 주석 처리 가능 
            point_create();

            // 높이 변경시 사용할 변수 
            let zh = 0;
            // 너무 낮은 높이에서 산에 가려지는 경우 발생 
            if (position.z <= 5000) {
                position.z = 30000;
            }
            // select 문에 대한 기능 수행 
            switch (text) {
                case "북쪽":
                    direction.setHeading(value);
                    break;
                case "서쪽":
                    direction.setHeading(value);
                    break;
                case "동쪽":
                    direction.setHeading(value);
                    break;
                case "남쪽":
                    direction.setHeading(value);
                    break;
                case "지면":
                    direction.setTilt(value);
                    position.z = 5000;
                    break;
                case "정면":
                    direction.setTilt(value);
                    position.z = 100;
                    break;
                case "높이 증가":
                    zh = position.z;
                    position.z = zh + 1000;
                    break;
                case "높이 감소":
                    zh = position.z;
                    position.z = zh1 - 1000;
                    break;
                default:
                    break;
            }
            // 카메라 보는 방향 조정하기
             map3d.lookat.moveTo(
                new vw.CameraPosition(
                    new vw.CoordZ(position.x, position.y, position.z),
                    new vw.Direction(direction.heading, direction.tilt, direction.roll)
                )
            );
            console.groupEnd();
        }

 

 

 

# 결과화면 

지도 전환 테스트 화면

# 테스트 화면 : https://jsbin.com/jusawikoze

 

Vworld Map 생성하기

 

output.jsbin.com


# 전체소스코드 

더보기

<!DOCTYPE html>

<html>

 

<head>

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    <title>Vworld Map 생성하기</title>

    <!-- vworld 스크립트 호출 -->

    <script type="text/javascript"

        src="https://map.vworld.kr/js/webglMapInit.js.do?version=2.0&apiKey=767B7ADF-10BA-3D86-AB7E-02816B5B92E9"></script>

 

</head>

 

<body>

    <!-- Map을 생성할 부분  -->

    <div id="vmap" style="position: absolute; width:99%;height:100vh;"></div>

    <!-- Map 생성 시 필요한 설정 부분  -->

    <div

        style="left:10px; position: absolute; z-index: 1; width: 200px; height: 150px; background-color: #ffffff80; padding: 5px;">

        <p>

            <input type="button" onclick="vwmap_create()" value="지도호출">

        </p>

 

        <p>

            <select id="select">

                <option value="0">북쪽</option>

                <option value="90">동쪽</option>

                <option value="-90">서쪽</option>

                <option value="180">남쪽</option>

                <option value="-90">지면</option>

                <option value="0">정면</option>

                <option value="0">높이 증가</option>

                <option value="0">높이 감소</option>

            </select>

            <input type="button" onclick="moveCamera()" value="카메라 위치 변경">

        </p>

    </div>

    <script type="text/javascript">

        var map3d = null;

        function vwmap_create() {

            var mapOptions = new vw.MapOptions(

                vw.BasemapType.GRAPHIC// 2D 초기배경지도 

                ""// 레이어목룩(3D에서 사용안함)

                vw.DensityType.BASIC// 2D 지도 전용

                vw.DensityType.BASIC// 2D 지도 전용

                false// 2D 지도 전용 

                new vw.CameraPosition(

                    //  vw.CoordZ(X,Y,Z) 클래스 : X(경도), Y(위도), Z(지면으로부터의 높이)

                    new vw.CoordZ(127.42538.1961548700),

                    // vw.Direction(heading,tilt,roll) 클래스 : heading(수평방향 회전각도), tilt(수직방향 회전각도),roll(카메라자체 회전각도)

                    new vw.Direction(-9000)

                ), // 2D, 3D 공통 사용 

                new vw.CameraPosition(

                    new vw.CoordZ(127.42538.1961548700),

                    new vw.Direction(0-900)

                ) // 2D, 3D 공통 사용

            );

 

            map3d = new vw.Map("vmap", mapOptions);

 

            // vw.EventProcess.add("test01", map3d.onMoveEnd, test01);

        }

 

        /**

         * 카메라 화면 이동하기  

         **/

        function moveCamera() {

            console.group('moveCamera');

            const e = document.getElementById("select");

            console.log(e);

            var value = parseInt(e.options[e.selectedIndex].value);

            var text = e.options[e.selectedIndex].text;

            console.log(value, text);

 

            const { directionposition } = map3d.getCurrentPosition();

            // 중심점 그리기

            point_create();

 

            let zh = 0;

            if (position.z <= 5000) {

                position.z = 30000;

            }

            switch (text) {

                case "북쪽":

                    direction.setHeading(value);

                    break;

                case "서쪽":

                    direction.setHeading(value);

                    break;

                case "동쪽":

                    direction.setHeading(value);

                    break;

                case "남쪽":

                    direction.setHeading(value);

                    break;

                case "지면":

                    direction.setTilt(value);

                    position.z = 5000;

                    break;

                case "정면":

                    direction.setTilt(value);

                    position.z = 100;

                    break;

                case "높이 증가":

                    zh = position.z;

                    position.z = zh + 1000;

                    break;

                case "높이 감소":

                    zh = position.z;

                    position.z = zh1 - 1000;

                    break;

                default:

                    break;

            }

            // 카메라 보는 방향 조정하기

             map3d.lookat.moveTo(

                new vw.CameraPosition(

                    new vw.CoordZ(position.x, position.y, position.z),

                    new vw.Direction(direction.heading, direction.tilt, direction.roll)

                )

            );

            console.groupEnd();

        }

 

        /**

         * 현재 중심점 포인트 생성 

         **/

        function point_create() {

            if (!map3d) return null;

 

            // 지도 센터 위치값을 반환(좌표계 EPSG:4326)

            const { directionposition } = map3d.getCurrentPosition();

            console.log('point_create', direction);

            console.log('point_create', position);

 

            var point1Coord = new vw.Coord(position.x, position.y);

            var pt = new vw.geom.Point(point1Coord);

            //   pt.setId("point1");

            pt.setImage("https://img.icons8.com/external-flatart-icons-solid-flatarticons/64/000000/external-map-point-real-estate-flatart-icons-solid-flatarticons-1.png");

            pt.setName("2차원 포인트 1");

            pt.setFont("고딕");

            pt.setFontSize(20);

            pt.create();

        }

    </script>

 

</body>

 

</html>

블로그 이미지

미나미나미

,

# vworld 3d Mouse 클릭 이벤트 

 

- vw.map.onClick 

  이벤트 생성 

     vw.map.onClick.addEventListener("이벤트 함수 정의');

  이벤트 제거 

    vw.map.onClick.removeEventListener("제거할 이벤트 함수");

 

- windowPosition, ecefPosition, cartographic

 * windowPosition : 지도 안에서의 마우스 x, y 좌표

 * ecefPosition : 이동시 마우스의 ECEF 좌표계 x, y, z 좌표

 * cartographic : 이동시 마우스의 WGS84 좌표(EPSG:4326).

 * 실제 경위도 좌표는  cartographic.longitudeDD, cartographic.latitudeDD를 쓰며, cartographic.height는 높이를 출력한다.

 

# vworld 3d point 생성 

 

 var point1Coord = new vw.Coord(x, y);

                var pt = new vw.geom.Point(point1Coord);

                //   pt.setId("point1");

                pt.setImage("https://img.icons8.com/external-flatart-icons-solid-flatarticons/64/000000/external-map-point-real-estate-flatart-icons-solid-flatarticons-1.png");

                pt.setName("클릭 이벤트");

                pt.setFont("고딕");

                pt.setFontSize(20);

                pt.create();


- 결과화면  : https://jsbin.com/yipuleroro

 

Vworld Map 생성하기

 

output.jsbin.com


#이벤트 발생 버튼 

<p>
            <input type="button" onclick="vwmap_create()" value="지도호출">
        </p>
        <p>
            <input type="button" onclick="point_create()" value="지도 센터 위치 포인트 생성">
        </p>
        <p>
            <input type="button" onclick="mouse_onclick_create()" value="왼쪽 마우스 클릭 이벤트 생성">
            <input type="button" onclick="mouse_onclick_remove()" value="왼쪽 마우스 클릭 이벤트 해제">
        </p>

# 포인트 생성 코드 

  function point_create() {
            if (!map3d) return null;

            // 지도 센터 위치값을 반환(좌표계 EPSG:4326)
            const { direction, position } = map3d.getCurrentPosition();
            console.log(direction);
            console.log(position);

            var point1Coord = new vw.Coord(position.x, position.y);
            var pt = new vw.geom.Point(point1Coord);
            //   pt.setId("point1");
            pt.setImage("https://img.icons8.com/external-flatart-icons-solid-flatarticons/64/000000/external-map-point-real-estate-flatart-icons-solid-flatarticons-1.png");
            pt.setName("2차원 포인트 1");
            pt.setFont("고딕");
            pt.setFontSize(20);
            pt.create();
        }

# map onclick 이벤트 생성, 포인트 생성 코드 

  /**
        * 왼쪽 마우스 버튼 클릭시 발생. 
        * Map객체의 onClick객체의 addEventListener로 이벤트 설정. removeEventListener()로 이벤트 제거.  
        * 전달되는 파라미터는 windowPosition, ecefPosition, cartographic
        * windowPosition : 지도 안에서의 마우스 x, y 좌표
        * ecefPosition : 이동시 마우스의 ECEF 좌표계 x, y, z 좌표
        * cartographic : 이동시 마우스의 WGS84 좌표(EPSG:4326).
        * 실제 경위도 좌표는  cartographic.longitudeDD, cartographic.latitudeDD를 쓰며, cartographic.height는 높이를 출력한다.
        * */
        var onclick_event = null;
        function mouse_onclick_create() {
            if (!map3d) return null;

            onclick_event = function (windowPosition, ecefPosition, cartographic) {
                console.group('onclick_event');
                console.log(arguments);
                console.log('windowPosition', windowPosition);
                console.log('ecefPosition', ecefPosition);
                console.log('cartographic', cartographic);
                // 경위도 좌표 
                var x = vw.Util.toDegrees(cartographic.longitude);
                var y = vw.Util.toDegrees(cartographic.latitude);
                var z = vw.Util.toDegrees(cartographic.height);
                console.log(x, y, z);

                var point1Coord = new vw.Coord(x, y);
                var pt = new vw.geom.Point(point1Coord);
                //   pt.setId("point1");
                pt.setImage("https://img.icons8.com/external-flatart-icons-solid-flatarticons/64/000000/external-map-point-real-estate-flatart-icons-solid-flatarticons-1.png");
                pt.setName("클릭 이벤트");
                pt.setFont("고딕");
                pt.setFontSize(20);
                pt.create();
                console.groupEnd();
            }
            map3d.onClick.addEventListener(onclick_event);
        }

        function mouse_onclick_remove() {
            if (!map3d) return null;

            map3d.onClick.removeEventListener(onclick_event);
        }

# 전체 소스 코드 

더보기

<!DOCTYPE html>

<html>

 

<head>

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    <title>Vworld Map 생성하기</title>

    <!-- vworld 스크립트 호출 -->

    <script type="text/javascript"

        src="https://map.vworld.kr/js/webglMapInit.js.do?version=2.0&apiKey=767B7ADF-10BA-3D86-AB7E-02816B5B92E9"></script>

 

    <!-- fontawesome icon  -->

    <link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css"

        integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />

</head>

 

<body>

    <!-- Map을 생성할 부분  -->

    <div id="vmap" style="position: absolute; width:99%;height:100vh;"></div>

    <!-- Map 생성 시 필요한 설정 부분  -->

    <div

        style="left:10px; position: absolute; z-index: 1; width: 200px; height: 150px; background-color: #ffffff80; padding: 5px;">

        <p>

            <input type="button" onclick="vwmap_create()" value="지도호출">

        </p>

        <p>

            <input type="button" onclick="point_create()" value="지도 센터 위치 포인트 생성">

        </p>

        <p>

            <input type="button" onclick="mouse_onclick_create()" value="왼쪽 마우스 클릭 이벤트 생성">

            <input type="button" onclick="mouse_onclick_remove()" value="왼쪽 마우스 클릭 이벤트 해제">

        </p>

    </div>

    <script type="text/javascript">

        var map3d = null;

        function vwmap_create() {

            /**

            vw.MapOptions(

                basemapType, // 2D 초기배경지도

                layersArr, // 레이어목록(3D에서 사용안함)

                controlDensity, // 2D지도 전용.

                interactionDensity, // 2D지도 전용.

                controlAutoArrange, // 2D지도 전용.

                homePosition, // 2D,3D 공통 사용.

                initPosition // 2D,3D 공통 사용.

            );

             **/

            var mapOptions = new vw.MapOptions(

                vw.BasemapType.GRAPHIC// 2D 초기배경지도 

                ""// 레이어목룩(3D에서 사용안함)

                vw.DensityType.BASIC// 2D 지도 전용

                vw.DensityType.BASIC// 2D 지도 전용

                false// 2D 지도 전용 

                new vw.CameraPosition(

                    //  vw.CoordZ(X,Y,Z) 클래스 : X(경도), Y(위도), Z(지면으로부터의 높이)

                    new vw.CoordZ(127.42538.1961548700),

                    // vw.Direction(heading,tilt,roll) 클래스 : heading(수평방향 회전각도), tilt(수직방향 회전각도),roll(카메라자체 회전각도)

                    new vw.Direction(-9000)

                ), // 2D, 3D 공통 사용 

                new vw.CameraPosition(

                    new vw.CoordZ(127.42538.1961548700),

                    new vw.Direction(0-900)

                ) // 2D, 3D 공통 사용

            );

 

            map3d = new vw.Map("vmap", mapOptions);

        }

 

        function point_create() {

            if (!map3d) return null;

 

            // 지도 센터 위치값을 반환(좌표계 EPSG:4326)

            const { directionposition } = map3d.getCurrentPosition();

            console.log(direction);

            console.log(position);

 

            var point1Coord = new vw.Coord(position.x, position.y);

            var pt = new vw.geom.Point(point1Coord);

            //   pt.setId("point1");

            pt.setImage("https://img.icons8.com/external-flatart-icons-solid-flatarticons/64/000000/external-map-point-real-estate-flatart-icons-solid-flatarticons-1.png");

            pt.setName("2차원 포인트 1");

            pt.setFont("고딕");

            pt.setFontSize(20);

            pt.create();

        }

 

        /**

        * 왼쪽 마우스 버튼 클릭시 발생. 

        * Map객체의 onClick객체의 addEventListener로 이벤트 설정. removeEventListener()로 이벤트 제거.  

        * 전달되는 파라미터는 windowPosition, ecefPosition, cartographic

        * windowPosition : 지도 안에서의 마우스 x, y 좌표

        * ecefPosition : 이동시 마우스의 ECEF 좌표계 x, y, z 좌표

        * cartographic : 이동시 마우스의 WGS84 좌표(EPSG:4326).

        * 실제 경위도 좌표는  cartographic.longitudeDD, cartographic.latitudeDD를 쓰며, cartographic.height는 높이를 출력한다.

        * */

        var onclick_event = null;

        function mouse_onclick_create() {

            if (!map3d) return null;

 

            onclick_event = function (windowPosition, ecefPosition, cartographic) {

                console.group('onclick_event');

                console.log(arguments);

                console.log('windowPosition', windowPosition);

                console.log('ecefPosition', ecefPosition);

                console.log('cartographic', cartographic);

                // 경위도 좌표 

                var x = vw.Util.toDegrees(cartographic.longitude);

                var y = vw.Util.toDegrees(cartographic.latitude);

                var z = vw.Util.toDegrees(cartographic.height);

                console.log(x, y, z);

 

                var point1Coord = new vw.Coord(x, y);

                var pt = new vw.geom.Point(point1Coord);

                //   pt.setId("point1");

                pt.setImage("https://img.icons8.com/external-flatart-icons-solid-flatarticons/64/000000/external-map-point-real-estate-flatart-icons-solid-flatarticons-1.png");

                pt.setName("클릭 이벤트");

                pt.setFont("고딕");

                pt.setFontSize(20);

                pt.create();

                console.groupEnd();

            }

            map3d.onClick.addEventListener(onclick_event);

        }

 

        function mouse_onclick_remove() {

            if (!map3d) return null;

 

            map3d.onClick.removeEventListener(onclick_event);

        }

 

    </script>

</body>

 

</html>

 

'vworld > 3d' 카테고리의 다른 글

4.vworld 방향 전환하기, 높이 조절하기  (0) 2021.09.25
2. vworld 3d map 이동하기  (0) 2021.09.21
1.vworld 3d Map 생성하기  (0) 2021.09.21
블로그 이미지

미나미나미

,