72 在Java中操作几何体Word文件下载.docx
《72 在Java中操作几何体Word文件下载.docx》由会员分享,可在线阅读,更多相关《72 在Java中操作几何体Word文件下载.docx(24页珍藏版)》请在冰豆网上搜索。
使用JGeometry类
Java中操作几何体的主要工具就是JGeometry类。
它使你可以对数据库中的几何体进行读写,同时也可以对几何体进行检查,创建新的几何体和对这些几何体进行一系列的转换。
1.几何体的读写
当你用SQL的SELECT语句读取对象类型(如SDO_GEOMETRY类型)时,JDBC返回一个Java结构--更精确地说,是oracle.sql.STRUCT对象。
在写一个对象的时候(用INSERT或UPDATE语句),你仍需要通过oracle.sql.STRUCT对象来传递。
对STRUCT的解码和构造都是相当复杂的,而OracleSpatialJavaAPI(JGeometry类)的主要目标就是使得这种操作变得简单。
JGeometry类提供了两种把STRUCT转换成JGeometry对象的方法:
load()方法用于读入STRUCT,返回JGeometry对象。
当你对由SELECT语句返回的几何体进行转换的时候,用该方法。
store()方法与load()方法相反。
它把JGeometry对象转换成可以通过INSERT或UPDATE语句写回数据库中的STRUCT对象。
图7-3展示了转换的过程。
(点击查看大图)图7-3
在Java中对几何体的读写
在OracleDatabase11g中,load()和store()方法得到了强化,以提供自己的为几何体对象而优化的序列化(pickling)及反序列化(unpickling)方法。
因此它们应当执行得更好。
对于读取一个几何体,首先要把这个对象以字节数组的形式读入,然后把这个数组传递给load()方法。
图7-4展示了这个过程。
图7-4
用优化的"
序列化"
工具在Java中对几何体进行读写
下面的这个例子,首先用结果集的getObject()方法,把各行的几何体对象提取为STRUCT类型,然后使用JGeometry的静态方法load()把它转换成JGeometry对象。
1.STRUCT
dbObject
=
(STRUCT)
rs.getObject
(1);
2.JGeometry
geom
JGeometry.load(dbObject);
要使用优化的反序列化工具(unpickler),首先使用结果集的getBytes()方法提取几何体到一个字节数组中。
然后再次使用JGeometry的静态方法load()把它转换成JGeometry对象。
1.byte[]
image
rs.
getBytes
(1);
JGeometry.load(image);
2.检查几何体
你现在可以用多个get()方法从几何对象中提取信息。
表7-2中总结了主要的方法。
在表7-3中附加的is()方法对几何体的特性进行了细化。
表7-2
JGeometry中主要的get()方法
方法
getType()
几何体类型(1表示点,2表示线,依次类推)
getDimensions()
维度
getSRID()
空间参考系ID
getNumPoints()
几何体中的点数
getPoint()
点对象的坐标(如果几何体是点)
getFirstPoint()
几何体中的第一点
getLastPoint()
几何体中的最后一点
getMBR()
几何体的MBR
getElemInfo()
SDO_ELEM_INFO数组的内容
getOrdinatesArray()
SDO_ORDINATES数组的内容
getLabelPoint()
返回SDO_POINT结构的坐标。
当用来填充线
或多边形几何体时,这通常被用来当标记点
getJavaPoint()
对一个单点对象来说,以java.awt.
geom.Point2D对象的形式返回点坐标
getJavaPoints()
对多点对象来说,返回一个java.awt.
geom.Point2D对象数组
getElements()
得到一个JGeometry对象数组,每个对
象都表示几何体的一个元素
getElementAt()
以JGeometry格式提取几何体的一个元素
createShape()
把几何体转换成java.awt.Shape对象,
为绘制和使用java.awt包中的工具做准备
表7-3
主要的JGeometryis()方法
方法
isPoint()
是不是点
isOrientedPoint()
是不是有向点
isCircle()
是不是圆
isGeodeticMBR()
是不是大地测量学的MBR
isMultiPoint()
是不是多点
isRectangle()
是不是矩形
hasCircularArcs()
几何体中是否包含弧
isLRSGeometry()
是不是一个线性参照的几何体
表7-2中的两个方法(getElements()和getElementAt())可以对复杂几何体的结构进行检查:
你可以提取独立的元素作为单独的JGeometry对象。
第一个方法返回所有元素到独立的JGeometry对象数组中。
第二个方法返回一个指定元素,通过其在几何体中的位置来标识。
警告:
对element术语的理解应参见OGCSimpleFeaturesforSQL规范。
例如,一个有孔多边形被看作是一个单元素,尽管它由多个环(在Oracle概念中,每个都是一个单元素)组成。
在第5章中讨论的验证函数(VALIDATE_GEOMETRY_WITH_CONTEXT()和EXTRACT())表现出同样的方式。
这就意味着getElements()方法不允许你从一个有孔多边形中提取孔。
元素的编号方式是从1开始的,而不是0。
3.创建几何体
向数据库中写入几何体(用INSERT或UPDATE语句)要求先创建一个新的JGeometry对象,并用JGeometry.store()方法把它转换成STRUCT。
然后把STRUCT传递给INSERT或UPDATE语句。
同load()方法一样,也可以使用速度更快的空间序列化工具。
图7-3和7-4展示了这两个方法。
下面是这两个方法的例子。
首先用JGeometry的静态方法store()把它转换为STRUCT,然后用setObject()方法把它插入到准备好的SQL语句中。
JGeometry.store
(geom,
dbConnection);
2.stmt.setObject
(1,dbObject);
使用优化的序列化工具除了与store()方法的参数顺序相反以外,其他的都一样:
先是定义数据库连接对象,然后是创建JGeometry对象。
(dbConnection,
geom);
有两种方法可以构造新的JGeometry对象。
一种是使用表7-4中的构造函数。
另一种方法是用静态的方法来创建不同的几何体。
表7-5列出了这些方法。
表7-4
JGeometry转换器
构造函数
目的
JGeometry(doublex,doubley,intsrid)
构造点
JGeometry(doublex,doubley,doublez,intsrid)
构造三维点
JGeometry(doubleminX,doubleminY,doublemaxX,
doublemaxY,intsrid)
创建矩形
JGeometry(intgtype,intsrid,int[]
elemInfo,double[]ordinates)
构造一般几何体
表7-5
静态JGeometry创建方法
创建方法
目的
createPoint(double[]coord,intdim,intsrid)
创建点
createLinearLineString(double[]coords,intdim,intsrid)
创建简单线串
createLinearPolygon(double[]coords,intdim,intsrid)
创建简单多边形
createMultiPoint(java.lang.Object[]coords,intdim,intsrid)
创建多重点对象
createLinearMultiLineString(java.lang.Object[]
coords,intdim,intsrid)
创建多重线串对象
createLinearPolygon(java.lang.Object[]coords,intdim,intsrid)
创建多重多边形
createCircle(doublex1,doubley1,doublex2,
doubley2,doublex3,doubley3,intsrid)
用圆上三点创建圆
createCircle(doublex,doubley,doubleradius,intsrid)
用中心和半径创建圆
4.修改存在的几何体
JGeometry类没有提供任何用于修改几何体的方法。
例如,没有方法用来从一个线上删除或添加一点。
为了执行那些更新,你需要用某个方法,如getOrdinatesArray(),来提取点序列,然后更新由此产生的Java数组,最后用其结果来创建一个新的JGeometry对象。
像先前讨论的那样把修改后的几何体写入到数据库中:
用store()方法把JGeometry对象转换为STRUCT,然后把STRUCT传给SQL中的INSERT或UPDATE语句。
5.处理几何体
JavaAPI也提供了大量的用于对几何体执行各种转换的方法。
表7-6中列出了主要的方法。
它们以JGeometry对象作为输入而以生成的新几何体作为输出。
注意,这些函数大部分都由数据库提供,并通过PL/SQL来对其进行调用,这一内容将在第9章中详述。
表7-6
几何体处理函数
buffer(doublebufferWidth)
在几何体周围形成一个缓冲区
simplify(doublethreshold)
简化几何体
densifyArcs(doublearc_tolerance)
在几何体中增加所有弧的密度
clone()
复制一个几何体
affineTransforms(...)
基于提供的参数(平移、缩放、旋转、切变、
反射)在输入几何体上应用仿射变换
projectToLTP(doublesmax,doubleflat)
把一个几何体从经度/纬度投影到一个切面上
projectFromLTP()
把一个几何体从一个本地切面投影到经度/纬度上
表7-7总结了API提供的一些辅助方法。
这些函数都不涉及JGeometry对象(除了equals),用来辅助处理一定的任务。
equals()函数用来比较两个JGeometry对象,判断它们是否相同。
然而,这种比较是基于几何体的内部编码的:
如果两个几何体的所有点的坐标都相同且顺序相同,那么就认为这两个几何体相同。
该方法不真正进行涉及容差的几何体的比较。
表7-7
几何体辅助函数
equals()
判断两个几何体是否相同
computeArc(doublex1,doubley1,doublex2,
doubley2,doublex3,doubley3)
从三个坐标点来计算这
个弧的中心、半径和角度
linearizeArc(doublex1,doubley1,double
x2,doubley2,doublex3,doubley3)
把一个弧转换成一组二维线段
reFormulateArc(double[]d)
通过重新计算角度重构一条弧
expandCircle(doublex1,doubley1,doublex2,
通过把圆转换成一组二维
线段来实现对其的线性化
monoMeasure(double[]coords,intdim)
判断一条线是否有变
长或缩短的方法
7.2.2
使用3D几何体:
J3D_Geometry类
OracleDatabase11g的一个主要的新功能就是它能够对复杂的3D对象(表面和立方体)进行建模。
新的J3D_Geometry类能够帮助你操作那些结构。
注意,它是JGeometry的子类,所以到目前为止,你已经了解的所有方法都是适用的。
像处理JGeometry一样,从数据库中读取J3D_Geometry对象,然后由JGeometry对象构造一个J3D_Geometry对象。
例如:
3.J3D_Geometry
geom3D
new
J3D_Geometry
(
4.geom.getType(),
geom.getSRID(),
5.geom.getElemInfo(),
geom.getOrdinatesArray()
6.);
仅通过使用规则的JGeometry.store()函数向数据库中写入J3D_Geometry对象:
geom3d);
与JGeometry相似,它提供给你大量的方法用来对几何体进行不同的操作。
表7-8总结了这些方法。
表7-8
3D几何体处理函数
anyInteract(J3D_GeometryA,doubletolerance)
判断两个三维几何体是否相交
extrusion(JGeometrypolygon,doublegrdHeight,
doubleheight,Connectionconn,booleancond,
doubletolerance)
通过对一个二维多边形
进行拉伸返回一个三维几何体
closestPoints(J3D_GeometryA,doubletolerance)
计算出两个三维几何体
中离得最近的点
getMBH(J3D_Geometrygeom)
对一个三维几何体返
回一个三维的边界框
validate(doubletolerance)
验证一个三维图像的有效性
area(doubletolerance)
计算一个面或立方体
中一面的面积
length(intcount_shared_edges,doubletolerance)
计算三维形状的长度
volume(doubletolerance)
计算三维立方体的体积
distance(J3D_GeometryA,doubletolerance)
计算两个三维几何体之间的距离
7.2.3
从3D几何体中提取元素:
ElementExtractor类
3D对象可能是复杂的。
立方体尤其符合这种情况。
一个复杂的立方体由多个简单的立方体组成。
这些简单的立方体又由表面组成,它们中的某些几何体构成了立方体中的孔。
表面本身由各种元素构成,而这些元素又由环组成。
ElementExtractor类使得对复杂对象的检查和独立组件的提取变得容易,如组成立方体的一个或多个表面。
注意,你也可以对一些规则的二维几何体使用提取器。
例如,在一个复杂的多边形中,它对提取一个环的线性等高线是很有用的。
可以通过两种方式使用提取器:
一个是提取指定的元素,另一个是对所有有效的元素进行迭代。
提示:
ElementExtractor类并不只局限于3D几何体,对2D图形也适用。
但是因为其输入必须是J3D_Geometry对象,所以首先要把JGeometry对象转换成一个J3D_Geometry对象。
1.提取独立元素
你需要做的就是调用静态的getElementByLabel()方法,传入一个用于唯一标记待提取几何体元素的标签。
这个标签是一个由逗号分隔的ID号码字符串,该号码指定了待返回的几何体的子集。
根据需要可以对以下列出的元素进行指定(对在最后一个指定的元素前的任何一个null元素,为其输入一个逗号)。
点ID
边ID
环ID
多边形ID
表面ID
立方体ID
多重立方体ID
这些ID号是每个元素在每一级上的序列号。
序列号从1开始:
在多重多边形中第一个多边形是多边形1。
它的环从1到N编号。
第二个多边形是多边形2,其中的环仍从1到N编号。
例如,下面的代码将从简单立方体的表面2中返回3号多边形:
1.J3D_Geometry
ring=ElementExtractor.
getElementByLabel(solid,"
0,0,0,3,2"
);
注意,当有错误发生时,J3D_Geometry中的validate()方法将返回这样一个标记。
你可以通过向ElementExtractor.getElementByLabel()传递这个标记来分离发生错误的元素。
2.对元素进行迭代
创建一个ElementExtractor对象,向它传递你的查询的参数。
这实际上将创建一个在一定详细程度上初始化的迭代器。
接着,你可以通过其nextElement()方法来逐个提取对象的组件。
然后还可以用另一个ElementExtractor对象进一步地检查第一次循环所得到的每个元素。
表7-9详细介绍了创建一个ElementExtractor对象所要用到的参数。
这些参数控制提取器的行为方式。
表7-9
ElementExtractor的参数
参数
geometry
待分析的3D几何体
firstElement
开始提取的位置,在几何体的SDO_ELEM_INFO
数组中被定义为偏移量。
默认值为0
extractionLevel
这个参数决定迭代器处理几何体中元素的方法。
请参见“提取级别”一节获取详细信息
allow_comp_sub_elements
指定为true(默认值)或false。
在
MULTICOMP_TOSIMPLE提取级别上,
用户可以通过把这个参数设置为FALSE,
从多个或复合几何体中直接提取
简单几何体。
默认值为TRUE,
这意味着用户将先从多几何体中提取复合几何体
3.提取级别
extractionLevel参数控制提取器的操作方式。
以下面的值对其进行指定。
名称为在类中所定义的常量。
Level0=MULTICOMP_TOSIMPLE:
它返回一个在多重几何体中的连续元素。
例如,它将返回多立方体中的每个立方体或多重多边形中的每个多边形。
可以把它想象成对元素的水平扫描。
Level1=INNER_OUTER:
如果存在,它将返回内部/外部元素。
对于多边形,它先返回外环,接着返回内环。
Level2=LOWER_LEVEL:
它返回子元素;
也就是,它返回下一个层次中的元素(例如,对立方体而言它的下一级是表面,而对于多边形而言是边,以此类推)。
让我们来看看一个有多个孔的多重多边形的简单例子。
我们首先用MULTICOMP_TOSIMPLE对其进行充分的扫描。
这将把这个多重多边形分解为单个简单的多边形。
下一步是从这些多边形中提取环。
首先要用INNER_OUTER扫描由第一步返回的多边形。
对于无孔的多边形,结果不会变。
但是对于那些有孔的多边形,你首先得到的是表示外环的多边形,然后是一个或多个表示内环的多边形。
最后,为了进一步分解几何体,用LOWER_LEVEL对每一个环进行扫描。
这种扫描将把每个环分解成一个边集--有两个顶点的简单的线串集。
下面是用提取器把一个多重几何体分解为元素的一个例子:
1.//
Create
extractor
2.ElementExtractor
e
ElementExtractor
3.geom3d,
0,
ElementExtractor.MULTICOMP_TOSIMPLE);
4.//
Geo