@ -1,32 +1,25 @@
package com.palnet.comn.utils ;
import java.io.BufferedReader ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.InputStreamReader ;
import java.nio.charset.StandardCharsets ;
import java.util.* ;
import java.util.concurrent.Callable ;
import java.util.concurrent.ExecutionException ;
import java.util.concurrent.ExecutorService ;
import java.util.concurrent.Executors ;
import java.util.concurrent.Future ;
import java.util.regex.Pattern ;
import com.palnet.comn.code.ErrorCode ;
import com.palnet.comn.exception.CustomException ;
import lombok.Data ;
import lombok.extern.slf4j.Slf4j ;
import org.json.simple.JSONArray ;
import org.json.simple.JSONObject ;
import org.json.simple.parser.JSONParser ;
import org.json.simple.parser.ParseException ;
import org.locationtech.jts.geom.Coordinate ;
import org.locationtech.jts.geom.GeometryFactory ;
import org.locationtech.jts.geom.Point ;
import org.locationtech.jts.geom.Polygon ;
import org.locationtech.jts.geom.* ;
import org.springframework.core.io.ClassPathResource ;
import lombok.extern.slf4j.Slf4j ;
import java.io.BufferedReader ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.InputStreamReader ;
import java.nio.charset.StandardCharsets ;
import java.util.* ;
import java.util.concurrent.* ;
import java.util.regex.Pattern ;
import java.util.stream.Collectors ;
@Slf4j
public class CoordUtils {
@ -51,7 +44,7 @@ public class CoordUtils {
}
public int getSize ( ) {
if ( this . allLocation = = null ) return 0 ;
if ( this . allLocation = = null ) return 0 ;
return this . allLocation . size ( ) ;
}
@ -101,14 +94,14 @@ public class CoordUtils {
String path = basePath + coords + "/" + baseFileName ;
try ( InputStream inputStream = new ClassPathResource ( path ) . getInputStream ( ) ;
try ( InputStream inputStream = new ClassPathResource ( path ) . getInputStream ( ) ;
BufferedReader reader = new BufferedReader ( new InputStreamReader ( inputStream , StandardCharsets . UTF_8 ) , 8192 ) ) {
JSONParser jsonParser = new JSONParser ( ) ;
jsonObject = ( JSONObject ) jsonParser . parse ( reader ) ;
} catch ( Exception e ) {
} catch ( Exception e ) {
log . error ( "" , e ) ;
}
return jsonObject ;
@ -157,7 +150,7 @@ public class CoordUtils {
jsonObject = null ;
}
if ( jsonObject ! = null & & jsonObject . get ( "distance" ) = = null ) {
if ( jsonObject ! = null & & jsonObject . get ( "distance" ) = = null ) {
depth = ( String ) jsonObject . get ( "CD" ) ;
@ -165,11 +158,11 @@ public class CoordUtils {
break ;
} else if ( jsonObject ! = null & & jsonObject . get ( "distance" ) ! = null ) {
} else if ( jsonObject ! = null & & jsonObject . get ( "distance" ) ! = null ) {
Double distances = ( Double ) jsonObject . get ( "distance" ) ;
if ( distance > distances ) {
if ( distance > distances ) {
distance = distances ;
@ -204,7 +197,7 @@ public class CoordUtils {
obj = parseGeoJson ( polygon , coordinate ) ;
if ( obj = = null ) return null ;
if ( obj = = null ) return null ;
return obj ;
@ -216,30 +209,31 @@ public class CoordUtils {
String address = "" ;
String path = basePath + depth . substring ( 0 , 2 ) + "/" + depth + "/" ;
String path = basePath + depth . substring ( 0 , 2 ) + "/" + depth + "/" ;
while ( true ) {
while ( true ) {
ClassPathResource classPathResource = new ClassPathResource ( path + baseFileName ) ;
ClassPathResource classPathResource = new ClassPathResource ( path + baseFileName ) ;
if ( ! classPathResource . exists ( ) ) {
if ( ! classPathResource . exists ( ) ) {
obj . put ( "add" , address ) ;
return obj ;
}
obj = parseGeoJson ( path + baseFileName , coordinate ) ;
obj = parseGeoJson ( path + baseFileName , coordinate ) ;
if ( obj = = null ) return null ;
if ( obj = = null ) return null ;
address + = " " + obj . get ( "KOR_NM" ) ;
path + = obj . get ( "CD" ) + "/" ;
path + = obj . get ( "CD" ) + "/" ;
}
}
public JSONObject parseGeoJson ( JSONObject obj , Coordinate coordinate ) throws IOException , ParseException {
Point point = geometryFactory . createPoint ( coordinate ) ;
@ -251,13 +245,13 @@ public class CoordUtils {
}
public JSONObject parseGeoJson ( String path , Coordinate coordinate ) {
public JSONObject parseGeoJson ( String path , Coordinate coordinate ) {
List < JSONObject > features = new ArrayList < JSONObject > ( ) ;
Point point = null ;
try ( InputStream inputStream = new ClassPathResource ( path ) . getInputStream ( ) ;
try ( InputStream inputStream = new ClassPathResource ( path ) . getInputStream ( ) ;
BufferedReader reader = new BufferedReader ( new InputStreamReader ( inputStream , "UTF-8" ) , 8192 ) ) {
JSONParser jsonParser = new JSONParser ( ) ;
@ -269,7 +263,7 @@ public class CoordUtils {
features = ( List < JSONObject > ) jsonObject . get ( "features" ) ;
} catch ( Exception e ) {
} catch ( Exception e ) {
log . error ( "" , e ) ;
}
@ -277,13 +271,14 @@ public class CoordUtils {
return this . contains ( features , point ) ;
}
public JSONObject contains ( List < JSONObject > features , Point point ) {
JSONObject result = null ;
Double standard = 10000000 . 0 ;
for ( int i = 0 ; i < features . size ( ) ; i + + ) {
for ( int i = 0 ; i < features . size ( ) ; i + + ) {
JSONObject geometry = ( JSONObject ) features . get ( i ) . get ( "geometry" ) ;
@ -291,13 +286,13 @@ public class CoordUtils {
List < JSONArray > coordinates = ( List < JSONArray > ) geometry . get ( "coordinates" ) ;
for ( int k = 0 ; k < coordinates . size ( ) ; k + + ) {
for ( int k = 0 ; k < coordinates . size ( ) ; k + + ) {
List < Coordinate > polygonPaths = new ArrayList < > ( ) ;
for ( Object coords : coordinates . get ( k ) ) {
for ( Object coords : coordinates . get ( k ) ) {
for ( int j = 0 ; j < ( ( JSONArray ) coords ) . size ( ) ; j + + ) {
for ( int j = 0 ; j < ( ( JSONArray ) coords ) . size ( ) ; j + + ) {
Object coord = ( ( JSONArray ) coords ) . get ( j ) ;
@ -317,17 +312,17 @@ public class CoordUtils {
}
Polygon polygon = geometryFactory . createPolygon ( polygonPaths . toArray ( new Coordinate [ ] { } ) ) ;
Polygon polygon = geometryFactory . createPolygon ( polygonPaths . toArray ( new Coordinate [ ] { } ) ) ;
if ( polygon . contains ( point ) ) {
if ( polygon . contains ( point ) ) {
return properties ;
} else {
} else {
Double distance = polygon . distance ( point ) ;
if ( standard > distance ) {
if ( standard > distance ) {
standard = distance ;
@ -344,11 +339,12 @@ public class CoordUtils {
/ * *
* 주소로 지역 바운더리 좌표 가져오기
*
* @param searchAdmCd DB에서 조회한 법정동 코드 [ 10자리 ]
* @param scope 지역 스코프 ,
* @return 지역좌표 반환
* /
public List < LocationCoordinateModel > getCoordinateByAddress ( String searchAdmCd , String scope ) {
public List < LocationCoordinateModel > getCoordinateByAddress ( String searchAdmCd , String scope ) {
String coordinateForderPath = this . getCodeForderPath ( searchAdmCd , scope ) ;
String admCd = this . removeAdmCd ( searchAdmCd , scope ) ;
@ -373,13 +369,13 @@ public class CoordUtils {
. findFirst ( ) ;
JSONObject result = resultJsonObject . orElseThrow ( ( ) - > new CustomException ( ErrorCode . DATA_NO ) ) ;
JSONObject geometry = ( JSONObject ) result . get ( "geometry" ) ;
JSONObject geometry = ( JSONObject ) result . get ( "geometry" ) ;
JSONArray coordinates = ( JSONArray ) geometry . get ( "coordinates" ) ;
for ( int i = 0 ; i < coordinates . size ( ) ; i + + ) {
JSONArray arrayNode = ( JSONArray ) ( ( JSONArray ) coordinates . get ( i ) ) . get ( 0 ) ;
for ( int i = 0 ; i < coordinates . size ( ) ; i + + ) {
JSONArray arrayNode = ( JSONArray ) ( ( JSONArray ) coordinates . get ( i ) ) . get ( 0 ) ;
List < Coordinate > coordinateList = new ArrayList < > ( ) ;
@ -404,9 +400,9 @@ public class CoordUtils {
}
/ * *
* 주소의 스코프 체크 기능 .
*
* @param address 스코프 체크할 주소
* @return 시 / 도 : ctprvn , 시 / 군 / 구 : sig , 읍 / 면 / 동 : emd , 리 : li
* /
@ -465,13 +461,14 @@ public class CoordUtils {
/ * *
* 법정동코드와 스코프에 맞춰 조회할 좌표파일 경로 가져오는 기능
*
* @param cd 조회할 법정동코드
* @param scope 스코프
* @return 폴더경로
* /
private String getCodeForderPath ( String cd , String scope ) {
private String getCodeForderPath ( String cd , String scope ) {
if ( cd . length ( ) ! = 10 ) return null ;
if ( cd . length ( ) ! = 10 ) return null ;
Stack < String > forderPathStack = new Stack < > ( ) ;
@ -488,7 +485,7 @@ public class CoordUtils {
StringBuilder forderPath = new StringBuilder ( ) ;
forderPath . append ( this . basePath ) ;
while ( ! forderPathStack . isEmpty ( ) ) {
while ( ! forderPathStack . isEmpty ( ) ) {
forderPath . append ( forderPathStack . pop ( ) ) ;
forderPath . append ( "/" ) ;
}
@ -500,33 +497,34 @@ public class CoordUtils {
/ * *
* 법정동코드를 10자리에 맞춰 0을 추가 [ DB조회를 위함 ]
*
* @param cd 10자리가 안되는 법정동코드
* @param scope 현재 법정동 코드의 스코프
* @return 10자리에 맞게 0이 추가된 법정동코드
* /
public String addAdmCd ( String cd , String scope ) {
public String addAdmCd ( String cd , String scope ) {
switch ( scope ) {
case "ctprvn" :
if ( cd . length ( ) < 2 ) break ;
if ( cd . length ( ) < 2 ) break ;
cd = cd . substring ( 0 , 2 ) ;
break ;
case "sig" :
if ( cd . length ( ) < 5 ) break ;
if ( cd . length ( ) < 5 ) break ;
cd = cd . substring ( 0 , 5 ) ;
break ;
case "emd" :
if ( cd . length ( ) < 8 ) break ;
if ( cd . length ( ) < 8 ) break ;
cd = cd . substring ( 0 , 8 ) ;
break ;
case "li" :
if ( cd . length ( ) < 10 ) break ;
if ( cd . length ( ) < 10 ) break ;
cd = cd . substring ( 0 , 10 ) ;
break ;
@ -540,7 +538,7 @@ public class CoordUtils {
StringBuilder sb = new StringBuilder ( ) ;
sb . append ( cd ) ;
for ( int i = 0 ; i < difference ; i + + ) {
for ( int i = 0 ; i < difference ; i + + ) {
sb . append ( "0" ) ;
}
@ -549,13 +547,14 @@ public class CoordUtils {
/ * *
* 스코프에 맞게 법정동코드 길이를 자르는 기능 .
*
* @param cd 잘라낼 법정동 코드
* @param scope 스코프
* @return 잘라진 법정동코드
* /
public String removeAdmCd ( String cd , String scope ) {
public String removeAdmCd ( String cd , String scope ) {
if ( cd . length ( ) ! = 10 ) throw new CustomException ( ErrorCode . NON_VALID_PARAMETER ) ;
if ( cd . length ( ) ! = 10 ) throw new CustomException ( ErrorCode . NON_VALID_PARAMETER ) ;
String result = "" ;
@ -585,4 +584,151 @@ public class CoordUtils {
}
public List < JSONObject > getPlace ( List < Coordinate > coords ) {
Geometry target = geometryFactory . createPolygon ( coords . toArray ( new Coordinate [ ] { } ) ) ;
List < JSONObject > result = new ArrayList < > ( ) ;
List < JSONObject > firstIntersectList = new ArrayList < > ( ) ;
for ( JSONObject location : this . allLocation ) {
List < JSONObject > features = ( List < JSONObject > ) location . get ( "features" ) ;
List < JSONObject > intersects = this . intersects ( features , target ) ;
firstIntersectList . addAll ( intersects ) ;
}
boolean isIntersect = firstIntersectList . stream ( ) . anyMatch ( properties - > properties . get ( "distance" ) = = null ) ;
if ( isIntersect ) {
firstIntersectList = firstIntersectList . stream ( ) . filter ( properties - > properties . get ( "distance" ) = = null ) . collect ( Collectors . toList ( ) ) ;
} else {
JSONObject jsonObject = firstIntersectList . stream ( ) . min ( Comparator . comparingDouble ( properties - > ( Double ) properties . get ( "distance" ) ) ) . orElse ( null ) ;
if ( jsonObject ! = null ) {
firstIntersectList = new ArrayList < > ( ) ;
firstIntersectList . add ( jsonObject ) ;
}
}
if ( firstIntersectList . isEmpty ( ) ) {
return result ;
}
for ( JSONObject properties : firstIntersectList ) {
List < JSONObject > subPropertiesList = getSubPropertiesByFile ( properties , target ) ;
if ( ! subPropertiesList . isEmpty ( ) ) {
result . addAll ( subPropertiesList ) ;
}
}
return result ;
}
private List < JSONObject > getSubPropertiesByFile ( JSONObject properties , Geometry target ) {
String depth = properties . get ( "CD" ) . toString ( ) ;
final String address = properties . get ( "KOR_NM" ) . toString ( ) ;
String path = basePath + depth . substring ( 0 , 2 ) + "/" + depth + "/" ;
String filename = path + baseFileName ;
ClassPathResource classPathResource = new ClassPathResource ( filename ) ;
List < JSONObject > result = new ArrayList < > ( ) ;
if ( ! classPathResource . exists ( ) ) {
return result ;
}
List < JSONObject > features = new ArrayList < > ( ) ;
try ( InputStream inputStream = new ClassPathResource ( filename ) . getInputStream ( ) ;
BufferedReader reader = new BufferedReader ( new InputStreamReader ( inputStream , "UTF-8" ) , 8192 ) ) {
JSONParser jsonParser = new JSONParser ( ) ;
JSONObject jsonObject = ( JSONObject ) jsonParser . parse ( reader ) ;
features = ( List < JSONObject > ) jsonObject . get ( "features" ) ;
} catch ( Exception e ) {
log . error ( "" , e ) ;
}
result = this . intersects ( features , target ) ;
boolean isIntersect = result . stream ( ) . anyMatch ( p - > p . get ( "distance" ) = = null ) ;
if ( isIntersect ) {
result = result . stream ( ) . filter ( p - > p . get ( "distance" ) = = null ) . collect ( Collectors . toList ( ) ) ;
} else {
JSONObject jsonObject = result . stream ( ) . min ( Comparator . comparingDouble ( p - > ( Double ) p . get ( "distance" ) ) ) . orElse ( null ) ;
if ( jsonObject ! = null ) {
result = new ArrayList < > ( ) ;
result . add ( jsonObject ) ;
}
}
result . forEach ( subProperties - > subProperties . put ( "address" , address + " " + subProperties . get ( "KOR_NM" ) ) ) ;
for ( JSONObject subProperties : result ) {
List < JSONObject > subSubPropertiesList = getSubPropertiesByFile ( subProperties , target ) ;
if ( ! subSubPropertiesList . isEmpty ( ) ) {
result . addAll ( subSubPropertiesList ) ;
}
}
return result ;
}
private List < JSONObject > intersects ( List < JSONObject > features , Geometry target ) {
List < JSONObject > intersectRs = new ArrayList < > ( ) ;
JSONObject isNotInstersectRs = null ;
double distance = Double . MAX_VALUE ;
for ( JSONObject feature : features ) {
JSONObject properties = ( JSONObject ) feature . get ( "properties" ) ;
JSONObject geometry = ( JSONObject ) feature . get ( "geometry" ) ;
List < JSONArray > coordinates = ( List < JSONArray > ) geometry . get ( "coordinates" ) ;
List < Polygon > polygons = new ArrayList < > ( ) ;
for ( JSONArray coordinate : coordinates ) {
List < Coordinate > polygonPaths = new ArrayList < > ( ) ;
for ( Object coords1 : coordinate ) {
for ( int j = 0 ; j < ( ( JSONArray ) coords1 ) . size ( ) ; j + + ) {
Object coord = ( ( JSONArray ) coords1 ) . get ( j ) ;
Object x = ( ( JSONArray ) coord ) . get ( 0 ) ;
Object y = ( ( JSONArray ) coord ) . get ( 1 ) ;
Double lon = y instanceof Double ? ( Double ) y : Double . valueOf ( ( Long ) y ) ;
Double lat = x instanceof Double ? ( Double ) x : Double . valueOf ( ( Long ) x ) ;
Coordinate areaCoord = new Coordinate ( lon , lat ) ;
polygonPaths . add ( areaCoord ) ;
}
polygonPaths . add ( polygonPaths . get ( 0 ) ) ;
}
Polygon polygon = geometryFactory . createPolygon ( polygonPaths . toArray ( new Coordinate [ ] { } ) ) ;
if ( ! polygon . isEmpty ( ) ) {
polygons . add ( polygon ) ;
}
}
MultiPolygon multiPolygon = null ;
if ( ! polygons . isEmpty ( ) ) {
multiPolygon = geometryFactory . createMultiPolygon ( polygons . toArray ( new Polygon [ ] { } ) ) ;
}
if ( multiPolygon ! = null ) {
boolean isIntersects = multiPolygon . intersects ( target ) ;
if ( isIntersects ) {
intersectRs . add ( properties ) ;
isNotInstersectRs = null ;
} else {
if ( intersectRs . isEmpty ( ) ) {
double targetDistance = multiPolygon . distance ( target ) ;
if ( targetDistance < distance ) {
distance = targetDistance ;
properties . put ( "distance" , distance ) ;
isNotInstersectRs = properties ;
}
}
}
} else {
log . debug ( "multiPolygon is null" ) ;
}
}
if ( intersectRs . isEmpty ( ) & & isNotInstersectRs ! = null ) {
intersectRs . add ( isNotInstersectRs ) ;
}
return intersectRs ;
}
}