Oracle——武汉空间数据库系统设计
闲暇时间整理一下本科做的一些课程设计,本文利用oracle数据建立了一个武汉的空间数据库系统,提供了空间信息查询,利用oracle提供的SDO_GEOMETRY对象访问空间对象。一、需求分析与系统设计1.1功能需求分析地理数据作为城市的重要数字化建设的一部分,在社会中应用广泛,涉及到普通百姓的吃穿住行方方面面,当前主要GIS软件功能实现流程如下:可见对地理信息的处理与分析可以服务社会经济的发展、服
闲暇时间整理一下本科做的一些课程设计,本文利用oracle数据建立了一个武汉的空间数据库系统,提供了空间信息查询,利用oracle提供的SDO_GEOMETRY对象访问空间对象。
目录
一、需求分析与系统设计
1.1功能需求分析
地理数据作为城市的重要数字化建设的一部分,在社会中应用广泛,涉及到普通百姓的吃穿住行方方面面,当前主要GIS软件功能实现流程如下:
可见对地理信息的处理与分析可以服务社会经济的发展、服务重大基础设施建设、服务政府治理、服务大众的衣食住行、服务抢险救灾,充分揭示经济社会发展和自然资源环境的空间分布规律,为政府制定和实施反战战略和规划、优化国土空间开发格局和各类资源的优化配置,服务政府宏观决策和空间治理体系建设提供重要依据,为推进生态环境保护、建设资源节约型和环境友好型社会提供重要支撑,为科学发展观的贯彻落实提供重要决策依据。
1.2系统功能模块设计
本系统主要针对了政府管理与民生问题进行了功能的实现,实现具体功能如下:
二、空间数据库结构设计
空间数据库的结构设计包括概念结构设计、逻辑结构设计和物理结构设计三大部分
2.1 概念结构设计和系统E-R图
由需求分析的结果可知,本系统设计的实体包括:
- Points地理重要标志点(车站,学校等):fid、shape、osm_id、name、type
- Railways铁路(含地铁):fid、shape、osm_id、name、type
- Roads城市道路:fid、shape、osm_id、name、type、oneway、bridge、maxspped
- Waterways水路:fid、shape、osm_id、name、type、width
- Buildings建筑物:fid、shape、osm_id、name、type
- Landuse土地利用:fid、shape、osm_id、name、type
- Natural自然人文景观:fid、shape、osm_id、name、type
2.2逻辑结构设计
数据库逻辑结构设计就是把概念模型设计阶段设计好的基本E-R图转化为选用的数据库卡支持的数据库模型相符合的逻辑结构,E-R图转化如下:
Points(fid、shape、osm_id、name、type)
Railways(fid、shape、osm_id、name、type)
Roads(fid、shape、osm_id、name、type、oneway、bridge、maxspped)
Waterways(fid、shape、osm_id、name、type、width)
Buildings(fid、shape、osm_id、name、type)
Landuse(fid、shape、osm_id、name、type)
Natural(fid、shape、osm_id、name、type)
2.3物理结构设计
数据库物理结构设计的任务就是根据具体计算机系统的特点,给给定的数据库系统确定合理的存储结构和存取方法,这里我们用到的是ORACLE的数据库系统,其中个我们的逻辑结构对应关系如下:
可以看到对于ORACLE而言,所有的空间对象都用的SDO_GEOMETRY这个对象来存储的,这个对象的主要结构如下:
SDO_GEOMETRY(
SDO_GTYPE NUMBER,
SDO_SRID NUMBER,
SDO_POINT SDO_POINT_TYPE,
SDO_ELEM_INFO SDO_ELEM_INFO_ARRAY,
SDO_ORDINATES SDO_ORDINATE_ARRAY,
)
三、空间数据编辑与入库
1、空间数据获取与编辑
关于数据的获取问题,推荐一个网站www.openstreetmap.org,这个网站下载来的数据应该是OSM类型,其中转换需要Arcgis,我自己又网上找了一个可以直接下载shp文件的网站https://extract.bbbike.org/,这个网站下载的数据需要导入arcgis然后导出才能用mapbuilder成功导入进ORACLE数据库,直接导入数据就进不去,不要问我为什么,可能arcgis会帮我们自动修复一些数据的错误吧。
导入数据库之后这些数据表感觉不太够,我最开始想到的功能就是对武汉七校联盟中的学校进行综合排名,所以给的数据肯定不行,我就进入各个学校的官网收集数据,包括学生总数,图书馆藏书量,教师总数,学校面积,2017年学校发表SCI论文数量,然后仅对光谷周围的武大、华科、地大、武理、华农进行排名。
还有用到编辑数据的是开始的缓冲区部分我是用arcgis做的,比如工业建筑的缓冲区,地铁站的缓冲区。
武汉地区的餐馆人均价格一开始也没有,我是用手机一个个查出来然后编辑进去的。
然后最后一个题水淹分析的DEM数据也通过了复杂的编辑,主要是通过经纬度裁剪,因为下载来的DEM数据是卫星拍摄的,比我的研究区大了很多,然后也试了好几个卫星的数据,最后发现ASTGTM2的数据比较合适,然后他的数据是DEM,只能用tif格式存储,我开始用c++的opencv读取数据一直读不对,后来用matlab读取修改了一下像素点的类型为UINT8,然后读取就可以了。
2、空间数据入库
空间数据主要利用的是mapbuilder这个程序吧,导入shp文件还是挺好用的,连接好数据库,选择shp文件并输入参数就可以了,只需要对应的mapbuilder版本就可以了。
下面是我导入进去的一些表和创建的一些表
四、系统功能实现与测试
4.1功能1
功能描述:随着武汉市的百万大学生留汉政策的实施,武汉大学生的住房问题需要解决,其中选址就是一个非常重要的一环,对于大学生而言,地铁出行是重要的一环,而且选房周围不能有工业建筑,否则会影响日常休息,本功能主要是在武汉地区地铁站周围1公里选择住房,然后筛选出其中在工业建筑2公里范围外的住房,选出来的就是最佳出行和居住的小区。
功能编码:
drop table sub_residential;
create table sub_residential(name varchar(255),geom mdsys.sdo_geometry);
declare
wkt varchar2(255);
wkt_clob clob;
g mdsys.sdo_geometry;
gt mdsys.sdo_geometry;
gb mdsys.sdo_geometry;
residentialname varchar2(255);
cursor incursor is
select i.geometry from industy_buffer i;
cursor subcursor is
select s.geometry from subway_buffer s;
cursor recursor(gm mdsys.sdo_geometry) is
select r.name,r.GEOMETRY from residential r
where sdo_geom.relate(gm, 'contains',r.geometry,0.005)='CONTAINS';
begin
open subcursor;
loop
fetch subcursor into g;
if subcursor%FOUND then
for recur in recursor(g) loop
fetch recursor into residentialname,gt;
if recursor%FOUND then
wkt_clob:=gt.get_wkt();
dbms_output.put_line(residentialname);
dbms_output.put_line(sys.dbms_lob.substr(wkt_clob,256,1));
insert into sub_residential values(residentialname,gt);
else exit;
end if;
end loop;
else exit;
end if;
end loop;
end;
drop table res_residential;
create table res_residential(name varchar(255),geom mdsys.sdo_geometry);
declare
wkt varchar2(255);
wkt_clob clob;
g mdsys.sdo_geometry;
gt mdsys.sdo_geometry;
gb mdsys.sdo_geometry;
residentialname varchar2(255);
cursor incursor is
select i.geometry from industy_buffer i;
cursor recursor(gm mdsys.sdo_geometry) is
select r.name,r.geom from sub_residential r
where sdo_geom.relate(gm, 'inside',r.geom,0.005)='FALSE';
begin
open incursor;
loop
fetch incursor into g;
if incursor%FOUND then
for recur in recursor(g) loop
fetch recursor into residentialname,gt;
if recursor%FOUND then
wkt_clob:=gt.get_wkt();
dbms_output.put_line(residentialname);
dbms_output.put_line(sys.dbms_lob.substr(wkt_clob,256,1));
--insert into sub_residential values(residentialname,gt);
else exit;
end if;
end loop;
else exit;
end if;
end loop;
end;
运行结果:
备注说明:本程序主要是通过两次过滤,第一次过滤在地铁站1km以外的住宅区,第二次过滤在工业建筑2km以内的住宅区
4.2功能2
功能描述:由于武汉处于长江地区,所以水淹分析特别重要,我对武汉地区的主要水路建立1.2KM的缓冲区,然后对缓冲区和住宅区进行空间查询,查询出有水淹隐患的住宅区,开始想做有源水淹分析,后来感觉oracle实现太复杂了,后来做无缘水淹分析,DEM数据老是出问题,输出不了正确结果,最后改成缓冲区分析,再加上空间查询。
功能编码:
declare
wkt varchar2(255);
wkt_clob clob;
g mdsys.sdo_geometry;
gt mdsys.sdo_geometry;
gb mdsys.sdo_geometry;
residentialname varchar2(255);
cursor bufcur is
select b.GEOMETRY from WATER_BUFFER b;
cursor rescursor(gm mdsys.sdo_geometry) is
select r.name,r.geometry from residential r
where sdo_geom.relate(gm,'CONTAINS',r.geometry,0.05)='CONTAINS';
begin
open bufcur;
loop
fetch bufcur into g;
if bufcur%FOUND then
for rescur in rescursor(g) loop
fetch rescursor into residentialname,gt;
if rescursor%FOUND then
wkt_clob:=gt.get_wkt();
dbms_output.put_line(residentialname);
dbms_output.put_line(sys.dbms_lob.substr(wkt_clob,256,1));
insert into flood_region values(residentialname,gt);
else exit;
end if;
end loop;
else exit;
end if;
end loop;
end;
运行结果:
备注说明:一共输出了52个小区,本来还想加上DEM高程分析的排除一些小区,无奈弄了一上午和一中午没弄出来,后来因为时间原因就放弃了,不过后面高级功能实现了。
4.3功能3
功能描述:对外地同学来说,平时周末放假想要出行,在计算学校到吃喝玩乐地点的距离时常常需要依赖地图,此功能可以通过输入两个点之间的名字,计算距离。
功能编码:
CREATE OR REPLACE function DISTANCE
( pointa_name varchar2,pointb_name VARCHAR2
)return number as
pointa mdsys.sdo_geometry;
pointb mdsys.sdo_geometry;
dis number;
BEGIN
select p.geometry into pointa from points p
where p.name=pointa_name;
select p.geometry into pointb from points p
where p.name=pointb_name;
dis:=sdo_geom.sdo_distance(pointa,pointb,0.005);
return dis;
END DISTANCE;
declare
dis number;
namea varchar2(255);
nameb varchar2(255);
begin
namea:='华中大';
nameb:='武汉大学';
dis:=DISTANCE(namea,nameb);
dbms_output.put_line(namea||'距离'||nameb||':');
dbms_output.put_line(dis||'米');
end;
运行结果:
4.4功能4
功能描述:随着经济的快速发展,武汉市的城市化进程势不可挡,老城区的拆迁已经迫在眉睫,而鲁磨路有很多老建筑需要拆迁,政府想要对鲁磨路周围进行拆迁建设新设施,那么拆迁赔偿预算的问题就非常重要,这个功能实现了对鲁磨路400米缓冲区范围内的建筑物拆迁赔偿计算,赔偿单价为2w/m2
功能编码:
delete from user_sdo_geom_metadata where table_name='LUMOLU_BUFFER';
drop table lumolu_buffer;
create table lumolu_buffer as select r.name,
sdo_geom.sdo_buffer(r.geometry,0.25,.05,
'arc_tolerance=0.005 unit=mile') geom
from roads r where r.name='³ĥ·';
insert into user_sdo_geom_metadata
(table_name,column_name,srid,diminfo)
values('lumolu_buffer','GEOM',8307,
sdo_dim_array(
sdo_dim_element('longitude',-180,180,0.5),
sdo_dim_element('latitude',-90,90,0.5))
);
declare
money number;
g mdsys.sdo_geometry;
gt mdsys.sdo_geometry;
gb mdsys.sdo_geometry;
area number;
cursor bufcursor is
select b.geom from lumolu_buffer b;
cursor housecursor(gm mdsys.sdo_geometry) is
select h.geometry from guanggubuildings h
where sdo_geom.relate(gm,'CONTAINS',h.geometry,0.005)='CONTAINS';
declare
money number;
g mdsys.sdo_geometry;
gt mdsys.sdo_geometry;
gb mdsys.sdo_geometry;
area number;
cursor bufcursor is
select b.geometry from lumolu3_buffer b;
cursor housecursor(gm mdsys.sdo_geometry) is
select h.geometry from guanggubuildings h
where sdo_geom.relate(gm,'CONTAINS',h.geometry,0.005)='CONTAINS';
begin
money:=0;
area:=0;
select sdo_geom.sdo_area(b.geometry,0.005) into area from lumolu3_buffer b;
dbms_output.put_line('缓冲区总面积:'||area||'平方米');
open bufcursor;
loop
fetch bufcursor into g;
if bufcursor%FOUND then
for housecur in housecursor(g) loop
fetch housecursor into gt;
if housecursor%FOUND then
area:=sdo_geom.sdo_area(gt,0.005);
money:=money+area*20000;
else exit;
end if;
end loop;
else exit;
end if;
end loop;
area:=money/20000;
dbms_output.put_line('拆迁鲁磨路总建筑面积:'||area||'平方米');
dbms_output.put_line('拆迁鲁磨路需要花费:'||money||'元');
end;
运行结果:
备注说明:结果出来为40亿左右,也不知道合不合理:),反正也不用我赔。
4.5功能5
功能描述:随着经济的发展和环境的改善,小区居民对环境和生活质量有了要求的提高,大部分居民希望自己能生活在安全卫生的小区,但是每个月物业费用到底该怎么规定呢,本题以保利华都为例,计算小区居民每个月人均物业费多少钱,参数为每平方米绿化维护5元,每米的道路维护5元,其他小区物业维护费用5w元,通过计算小区住房面积和道路长度对小区的物业费进行计算。
功能编码:
declare
g mdsys.sdo_geometry;
road_length number;
population number;
fee number;
begin
select geometry into g from landuse where name='保利·华都';
select SUM(sdo_geom.sdo_length(r.geometry,m.diminfo))/2 into road_length
from roads r,user_sdo_geom_metadata m
where sdo_geom.relate(g,'CONTAINS',r.geometry,0.005)='CONTAINS';
select SUM(sdo_geom.sdo_area(b.geometry,0.05))/2
into population from buildings b
where sdo_geom.relate(g,'CONTAINS',b.geometry,0.005)='CONTAINS';
fee:=(sdo_geom.sdo_area(g,0.05)*5+road_length*10+50000)/population;
dbms_output.put_line('保利·华都物业费:'||fee||'/元/人/月');
dbms_output.put_line('保利·华都小区人口数:'||population);
dbms_output.put_line('保利·华都小区面积:'||sdo_geom.sdo_area(g,0.05));
dbms_output.put_line('保利·华都小区道路长度:'||road_length);
end;
运行结果:
备注说明:做之前感觉挺复杂,做完感觉分步做就很容易,先选小区区域,再在区域里面查询住宅区面积和道路长度,几个查询就可以实现
4.6功能6
功能描述:武汉长江大桥是万里长江的第一座大桥,从1957年使用到现在已经经历了快70年了,近期市政府决定要对长江大桥进行检查维修工作,并对长江大桥的使用情况进行长期评估预测,所以要对周边的路段进行封路告示牌提醒,本路段提取了与长江大桥相交的路段信息,供交管系统人员使用。
功能编码:
declare
wkt_clob clob;
name varchar2(255);
g mdsys.sdo_geometry;
gt mdsys.sdo_geometry;
cursor roadcur is select
r.name,r.geometry from roads r
where sdo_geom.relate(r.geometry,'ANYINTERACT',g,0.05)='TRUE';
begin
select geometry into g from roads where name='武汉长江大桥';
open roadcur;
loop
fetch roadcur into name,gt;
if roadcur%FOUND then
wkt_clob:=g.get_wkt();
dbms_output.put_line(name);
dbms_output.put_line(sys.dbms_lob.substr(wkt_clob,256,1));
else
exit;
end if;
end loop;
end;
运行结果:
4.7功能7
功能描述:武汉今年来城市建设做出了巨大努力,其中地铁建设是武汉值得骄傲的一件事,从武汉第一条地铁建成投入使用以来,享受地铁带来的交通便利已经是武汉人习以为常的出行体验了,市政府决定粗略研究武汉地铁的惠民人数即地铁周围400m缓冲区的小区的总人数,人口密度按800人/公顷算(0.08人/m2)。
功能编码:
declare
g mdsys.sdo_geometry;
gt mdsys.sdo_geometry;
gb mdsys.sdo_geometry;
all_area number;
area number;
cursor subcur is select geom from rail_buffer;
cursor rescur(gm mdsys.sdo_geometry) is select r.geometry,
sdo_geom.sdo_area(r.geometry,0.005) from residential r
where sdo_geom.relate(gm,'ANYINTERACT',r.geometry,0.005)='TRUE';
begin
all_area:=0;
area:=0;
open subcur;
loop
fetch subcur into gt;
if subcur%FOUND then
for rcur in rescur(gt) loop
fetch rescur into gb,area;
if rescur%FOUND then
--dbms_output.put_line(area);
all_area:=all_area+area;
else exit;
end if;
end loop;
else exit;
end if;
end loop;
dbms_output.put_line('武汉地铁惠民总人数:'||to_char(all_area*0.08,'999999'));
end;
运行结果:
然后使用arcgis显示地铁线路:
备注说明:上图是在ARCGIS上面选择的武汉市地铁的总线路,结果显示为729208人,感觉挺符合实际的。
五、结合高级语言混合编程
5.1matlab连接oracle数据库编程
功能描述:在地大读了这么多年,我想对武汉七校联盟的部分高校就某些指标进行排名与打分(其实是上完数学建模通选课想实际应用学到的东西,哈哈),本题给光谷片区部分高校进行主成分分析并进行排序结果输出,进行评价的指标有学生总数,图书馆藏书量,教师总数,学校面积,2017年学校发表SCI论文数量(数据有点难找,就先只找了这么多,只对光谷周围的武大,华科,武汉理工,华农和地大进行排名)。
功能编码:
conn_odbc = database('OracleServiceORCL','wuhan','3837');
curs=exec(conn_odbc,'select name,population,libraries,teachers,area,sci from SCHOOL');
curs = fetch(curs);
school = curs.Data;
school_name=school(:,1);
data=school(:,2:6);
for i=1:1:5
for j=1:1:5
school_data(i,j)=cell2mat(data(i,j));
end
end
stddata=zscore(school_data);%数据标准化
r=corrcoef(school_data);%计算相关系数矩阵
[x,y,z]=pcacov(r);%计算特征向量x,特征值y,贡献率z
contr=cumsum(z);%计算累计贡献率
f=repmat(sign(sum(x)),size(x,1),1);
x=x.*f;%修改特征向量的正负号
num=3;%取前三个主成分,此时贡献率已经超过93%
df=stddata*x(:,(1:num));%计算各个主成分的得分
tf=df*z(1:num)/100%计算高校的综合得分
[stf,ind]=sort(tf,'descend');%对得分结果降序排列
stf+10-stf(1),school_name(ind)%以十分制进行排名
close(curs);
close(conn_odbc);
运行结果:
可以看到华科第一武大第二,咱们地大排出来时最后一名:( 可能输在学校面积吧哈哈
备注说明:利用matlab(对矩阵数据处理方便)连接oracle数据库进行编程,利用主成分分析对高校综合得分进行排序,matlab连接ORACLE有好几种方法,我是用ODBC连接的,暂时没有访问到空间数据,仅仅涉及到属性数据。
5.2JAVA连接oracle数据库编程
功能描述:随着九年义务教育的实行,人们的文化程度普遍提高,家长们开始重视孩子的教育问题,那么离学校近也成了很多家长选房买房的标准,本功能用JAVA语言通过JDBC连接ORACLE访问POINTS表中的SDO_GEOMETRY对象,并且访问的POINTS的TYPE必须为SCHOOL,然后将得到的坐标和投影坐标转换,将点投放在武汉市部分地区底图上
功能编码:
import oracle.sql.STRUCT;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.sql.*;
import oracle.spatial.geometry.JGeometry;
import oracle.sql.STRUCT;
public class Main {
public static Connection getConnection(){
Connection conn=null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url="jdbc:oracle:thin:@localhost:1521/pdborcl";
String username="wuhan";
String password="3837";
conn= DriverManager.getConnection(url,username,password);
}catch (ClassNotFoundException e){
e.printStackTrace();;
}catch (SQLException e){
e.printStackTrace();
}
return conn;
}
public static void main(String[] args) {
BufferedImage img = null;
try {
img = ImageIO.read(new File("./wuhan.png"));
} catch (IOException e) {
e.printStackTrace();
}
Frame frame = new Frame("武汉学校缓冲区示意图");
frame.setSize(img.getWidth(),img.getHeight());
frame.setLocation(500, 50);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
String sql="select p.geometry from points p where type='school'";
Connection connection=getConnection();
try{
Statement statement=connection.createStatement();
ResultSet resultSet =statement.executeQuery(sql);
while(resultSet.next()){
STRUCT st = (STRUCT) resultSet.getObject("geometry");
JGeometry geom=JGeometry.load(st);
int dimensionality=geom.getDimensions();
double[] geomxy=geom.getFirstPoint();
System.out.println(geomxy[0]);
System.out.println(geomxy[1]);
double pointx=(geomxy[0]-114.143)*2921;
double pointy=(30.649-geomxy[1])*3395;
System.out.println(pointx);
System.out.println(pointy);
Graphics2D g2d=(Graphics2D)img.getGraphics();
g2d.setColor(Color.RED);
g2d.setFont(new Font("宋体",Font.PLAIN,30));
g2d.setStroke(new BasicStroke(12));
//g2d.drawString("*",(int)pointx,(int)pointy);
g2d.fillOval((int)pointx,(int)pointy,50,50);
//g2d.drawString("helloworld",50,50);
JLabel label = new JLabel(new ImageIcon(img));
frame.add(label);
label.setBounds(0, 0,img.getWidth(),img.getHeight());
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
运行结果:
然后使用arcgis进行验证,发现基本一致,效果还挺不错的
5.3JAVA连接oracle数据库编程2
功能描述:寒假快到了,在外地上大学的朋友也快回武汉了,小明准备和高中几个同学一起约着吃一顿饭一起谈谈大学的生活,小明和同学准备在武大集合,然后找附近的吃饭地点,要求是人均消费在50到220之间,越贵越好,因为很久没见还是吃点好的,最好在武大附近5KM之内,太远了也比较浪费时间,本功能实现了对某一地点的周围指定区域的餐馆查询在价格接受范围内按照人均价格降序排列输出并可视化标记在地图上。
功能编码:
import oracle.sql.STRUCT;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.sql.*;
import oracle.spatial.geometry.JGeometry;
public class Main {
public static Connection getConnection(){
Connection conn=null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url="jdbc:oracle:thin:@localhost:1521/pdborcl";
String username="wuhan";
String password="3837";
conn= DriverManager.getConnection(url,username,password);
}catch (ClassNotFoundException e){
e.printStackTrace();;
}catch (SQLException e){
e.printStackTrace();
}
return conn;
}
public static void main(String[] args) {
BufferedImage img = null;
try {
img = ImageIO.read(new File("./wuhan.png"));
} catch (IOException e) {
e.printStackTrace();
}
Frame frame = new Frame("武汉学校缓冲区示意图");
frame.setSize(img.getWidth(),img.getHeight());
frame.setLocation(500, 50);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
double pointx=0;
double pointy=0;
double pointa=0;
double pointb=0;
String sql="select s.geometry from school s where s.name='武汉大学'";
Connection connection=getConnection();
try{
Statement statement=connection.createStatement();
ResultSet resultSet =statement.executeQuery(sql);
while(resultSet.next()){
STRUCT st = (STRUCT) resultSet.getObject("geometry");
JGeometry geom=JGeometry.load(st);
int dimensionality=geom.getDimensions();
double[] geomxy=geom.getFirstPoint();
pointx=(geomxy[0]-114.143)*2921-25;
pointy=(30.649-geomxy[1])*3395-25;
//System.out.println(pointx);
//System.out.println(pointy);
Graphics2D g2d=(Graphics2D)img.getGraphics();
g2d.setColor(Color.RED);
g2d.setFont(new Font("宋体",Font.PLAIN,30));
g2d.setStroke(new BasicStroke(12));
g2d.fillOval((int)pointx,(int)pointy,50,50);
JLabel label = new JLabel(new ImageIcon(img));
frame.add(label);
label.setBounds(0, 0,img.getWidth(),img.getHeight());
}
}catch(SQLException e){
e.printStackTrace();
}
sql="select r.name,r.avg_price,r.geometry from restaurant r \n" +
" where r.avg_price<250 and avg_price>50 order by avg_price desc";
try{
Statement statement=connection.createStatement();
ResultSet resultSet =statement.executeQuery(sql);
while(resultSet.next()){
String name=resultSet.getString("name");
double avg_price=resultSet.getDouble("avg_price");
STRUCT st = (STRUCT) resultSet.getObject("geometry");
JGeometry geom=JGeometry.load(st);
int dimensionality=geom.getDimensions();
double[] geomxy=geom.getFirstPoint();
pointa=(geomxy[0]-114.143)*2921-25;
pointb=(30.649-geomxy[1])*3395-25;
//System.out.println(pointa);
//System.out.println(pointb);
double dis=38*Math.sqrt((pointa-pointx)*(pointa-pointx)+(pointb-pointy)*(pointb-pointy));
//C = sin(MLatA)*sin(MLatB)*cos(MLonA-MLonB) + cos(MLatA)*cos(MLatB)
//Distance = R*Arccos(C)*Pi/180;
//System.out.println(dis);
if(dis<5000)
{
Graphics2D g2d=(Graphics2D)img.getGraphics();
g2d.setColor(Color.BLUE);
g2d.setFont(new Font("宋体",Font.PLAIN,10));
g2d.setStroke(new BasicStroke(12));
g2d.fillOval((int)pointa,(int)pointb,10,10);
JLabel label = new JLabel(new ImageIcon(img));
frame.add(label);
label.setBounds(0, 0,img.getWidth(),img.getHeight());
System.out.println("武大距离"+name+(int)dis+"米"+" 人均消费"+avg_price+"元");
System.out.println("");
}
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
运行结果:
红色的是武大,蓝色的是周围可供选择的餐馆,然后程序也输出了距离和消费信息并降序排列
备注说明:可以看到输出的结果都符合条件,因为底图太小了,本来想在底图上面的对应位置输出的,结果位置太挤看不太清,最后在程序就直接输出了。
5.4C++连接oracle数据库编程
功能描述:武汉地区是一个非常安全的地方,没有地震没有海啸没有泥石流,如果要说有,洪水确实是危害市民的一大隐患,1998年武汉就发生了洪水,本功能以长江为源,对武汉进行有源水淹分析,进行地质灾害的抢险救灾工作的部署,通过种子生长算法达到要求,生长条件是DEM值小于20(数据处理花了挺长时间的:)最后还好做出来了,不然要亏死了 )。
功能编码:
#include <iostream>
#include <stack>
#include <opencv2\opencv.hpp>
#include <opencv2/imgproc/types_c.h>
#include <time.h>
using namespace std;
using namespace cv;
// 8 邻域
static Point connects[8] = { Point(-1, -1), Point(0, -1), Point(1, -1), Point(1, 0), Point(1, 1), Point(0, 1), Point(-1, 1), Point(-1, 0) };
int changex(int x)
{
return (int)(0.810958*x);
}
int changey(int y)
{
return (int)(0.941529*y);
}
int main()
{
Mat src = imread("src.tif", 0);
Mat wuhan = imread("wuhan.png", 0);
/*Mat res = Mat::zeros(src.rows, src.cols);*/
Mat res;
src.copyTo(res);
// 用于标记是否遍历过某点
Mat flagMat = Mat::zeros(src.rows, src.cols, CV_8U);
// 初始种子点
stack<Point> seeds;
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
if (src.at<uchar>(i, j) <= 6)
{
res.at<uchar>(i, j) = 255;
//wuhan.at<uchar>(changex(i), changey(j)) = 255;
seeds.push(Point(j, i));
flagMat.at<uchar>(i, j) = 1;
}
}
}
imwrite("res.tif", res);
while (!seeds.empty())
{
Point seed = seeds.top();
seeds.pop();
// 遍历8邻域
for (size_t i = 0; i < 8; i++)
{
int tmpx = seed.x + connects[i].x;
int tmpy = seed.y + connects[i].y;
if (tmpx < 0 || tmpy < 0 || tmpx >= src.cols || tmpy >= src.rows)
continue;
//如果该领域超出图像像素范围,进行下次循环
int tmgray = src.at<uchar>(tmpy, tmpx);
if (tmgray < 22 && flagMat.at<uchar>(tmpy, tmpx) == 0)
{
res.at<uchar>(tmpy, tmpx) = 255; // 生长
//wuhan.at<uchar>(changex(tmpy), changey(tmpx)) = 255;
flagMat.at<uchar>(tmpy, tmpx) = 1; // 标记
seeds.push(Point(tmpx, tmpy)); // 种子压栈
}
}
}
imwrite("res1.tif", res);
imwrite("res2.tif", wuhan);
waitKey(0);
return 0;
}
运行结果:
选中的种子点区域(长江流域)
生长出的DEM高程小于20并且在流域旁边可能被水淹到的区域)
结合武汉的地图进行输出:
备注说明:本来想在oracle里面实现的,试了之后发现实现不了,就改成简单的输出了。最后这个改了好几遍,一开始是图像大小不匹配导致指针越界,然后编辑图像和DEM数据大小相同后处理就可以了。注意彩色图像和灰度图像的赋值语句就可以了。
为武汉地区的开发者提供学习、交流和合作的平台。社区聚集了众多技术爱好者和专业人士,涵盖了多个领域,包括人工智能、大数据、云计算、区块链等。社区定期举办技术分享、培训和活动,为开发者提供更多的学习和交流机会。
更多推荐
所有评论(0)