이동하는 장비가 어느 블록 내에 있는지 찾아야 하는 경우가 생겼다.
장비의 이동 위치는 위,경도 값으로 DB 에 저장되어 있었고, 블록의 위, 경도 정보는 xml 파일에 있는 상태라 우선 xml 파일의 정보를 DB 에 저장했다.
1. Block 의 Polygon 정보가 들어 있는 xml 파일
<Location version="201904250931">
<Bound id="BE-VX02" che="true">
<Point x="31.744928" y="45.758862" />
<Point x="31.742374" y="45.761635" />
<Point x="31.742670" y="45.761791" />
<Point x="31.745214" y="45.759014" />
</Bound>
<Bound id="BE-VX01" che="true">
<Point x="31.742182" y="45.761986" />
<Point x="31.747015" y="45.763622" />
<Point x="32.747166" y="45.763371" />
<Point x="31.742338" y="45.761734" />
</Bound>
...
<Bound id="BE-VX65" che="true">
<Point x="31.753398" y="45.762699" />
<Point x="31.753183" y="45.762687" />
<Point x="31.753007" y="45.762760" />
<Point x="31.752147" y="45.763534" />
<Point x="31.751848" y="45.763610" />
<Point x="31.751342" y="45.763477" />
<Point x="31.749565" y="45.764622" />
<Point x="31.749275" y="45.764671" />
...
</Location>
2. xml 파일에서 Bound ID 와 Polygon 좌표 정보를 저장할 Table 생성(mariaDB)
CREATE TABLE `evt_bound` (
`reg_seq` bigint(20) NOT NULL AUTO_INCREMENT,
`bnd_id` varchar(20) DEFAULT NULL,
`bnd_pol` polygon DEFAULT NULL, PRIMARY KEY (`reg_seq`) )
ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
3. xml 파일 읽어 데이터를 Table 에 저장하는 스크립트
import xml.etree.ElementTree as elemTree
import pymysql
from mysql.connector import Error
def main():
tree = elemTree.parse('D:/Geofence_UTF_HSEDIT.xml')
try:
con = pymysql.connect(host="db_ip", user="db_id", password="db_pwd",
db='db_name', charset='utf8')
cur = con.cursor()
for bound in tree.findall('./Bound'):
bound_id = bound.get('id')
points = bound.findall('./Point')
pol_text = ''
for point in points:
# print(point.attrib)
pol_text += point.get('y') + ' ' + point.get('x') + ', '
pol_text += points[0].get('y') + ' ' + points[0].get('x')
pol_text = 'POLYGON((' + pol_text + '))'
# insert into 테이블 (POLYGON_TYPE_COLUMN명)
# values (POLYGONFROMTEXT('POLYGON(('위치0 위치1 위치2 ... 위치0))'))
sql = """insert into evt_bound ( bnd_id, bnd_pol )
values (%s, POLYGONFROMTEXT(%s))
"""
cur.execute(sql, (bound_id, pol_text))
con.commit()
except Error as e:
print("Error MySQL ", e)
finally:
cur.close()
con.close()
print("MySQL connection is closed")
if __name__ == '__main__':
main()
스크립트의 코멘트로 기록해두었지만 mariaDB(mySQL) 의 Polygon 타입 컬럼에 값 저장할 때는 좌표값을 ','으로 구분하여 나열하면 되는데 단, 닫힌 도형이 되어야 하므로 첫 번째 좌표값을 마지막에 다시 위치시켜줘야 한다. 그러므로 실제 저장되는 형태는 다음과 같은 식이 될 것이다.
insert into evt_bound ( bnd_id, bon_pol )
values ( 'BE-VX02', PolygonFromText('POLYGON((40.758862 29.74492, 40.761635 29.742374, 40.761791 29.742670, 40.759014 29.745214, 40.758862 29.74492))') )
준비는 다 되었고 이제 장비의 좌표값이 들어 있는 테이블과 연결하여 어느 블록 안에 있는지 찾아보자.
SELECT a.mach_id, a.pos_lat, a.pos_lon, b.bnd_id
FROM evt_mach_pos_hst a, evt_bound b
WHERE ST_CONTAINS(b.bnd_pol, GEOMFROMTEXT(CONCAT('POINT(',pos_lat,' ',pos_lon,')' )))
mariaDB 에서 제공하는 ST_CONTAINS 함수를 이용하여 장비가 들어가 있는 bound 의 ID 를 구해봤다.
'Slack 채널 정리' 카테고리의 다른 글
JpaSystemException: No default constructor for entity (0) | 2019.12.03 |
---|---|
대량 데이터 조회 비동기 처리 (0) | 2019.12.03 |
ZeroMQ 잡담 (0) | 2019.12.02 |
vim macro (0) | 2019.12.02 |
LocalDateTime 타입의 값 비교 - ChronoUnit (0) | 2019.12.02 |