spatial中经纬度字符串和图形之间的转换

(接上篇文章)下面主要来讲讲它们是如何将经纬度-->图形和图形-->经纬度的。

  1. 经纬度-->图形:

通 过它们的readShape(String value)方法即可完成,该方法会首先去执行readStandardShape方法,这个方法在SpatialContext和 JtsSpatialContext中的处理是不一样的,前一个主要是针对点线面的(即2D场景),后一个是针对多种不规则形式的(即3D场景)。下面讲 讲这两个类的具体的readShape实现: ①解析一个点的时候你传递给Spatial的形式应该是:x,y或 x y或x y a b三种形式的,x,y形式的会被认为是经纬度,x y形式的会被认为是点坐标,x y a b会被认为是矩形。所以x,y会使用如下流程解 析:ShapeReadWriter.readStandardShape——ShapeReadWriter.readLatCommaLonPoint——ParseUtils.parseLatitudeLongitude(返 回经纬度数组latLon[])——SpatialContext.makePoint(latLon[1],latLon[0])(返回Point实 例)。 解析x y的流程和x,y的流程基本上一致,只不过是直接进入SpatialContext.makePoint(x,y)。

② 解析x y a b(即矩形形式的)的流程为SpatialContext.makeRectangle(x y a b)ànew RectangleImpl(x y a b)(返回Rectangle实例),在方法makeRectangle方法中,需要判断x y a b和worldBounds的变量之间的大小关系(之前说过worldBounds定义的是查询的范围,所以不能超过worldBounds定义的值)。

③ 解析一个圆的时候你传递给Spatial的形式应该是Circle(x y d=z)或Circle(x y z),其中Circle可以写成CIRCLE,d可以写成distance,x和y代表圆心的坐标,d代表半径。解析出x和y值之后使用①中的方式先画一 个点出来,然后使用SpatialContext.makeCircle(圆心,半径)方法画圆。画圆时返回的是Circle接口的实现类 CircleImpl,它持有圆心和半径,还有一个包围盒(即该圆围住的那些地方,它也是一个Rectangle实例),包围盒的获取是由 DistanceCalculator的实现类(上面说过的calculator)实现的,默认是 GeodesicSphereDistCalc.Haversine(Haversine为继承GeodesicSphereDistCalc的内部 类),具体流程 为:GeodesicSphereDistCalc.calcBoxByDistFromPt(Point,radius,ctx,rectangle)——DistanceUtils.calcBoxByDistFromPtDEG(point.getY,point.getX,radius,ctx, rectangle),该方法主要是根据圆心和半径获取到一个矩形区域的四个点的位置并返回这四个点组成的Rectangle。具体的算法参看http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates和http://gis.stackexchange.com/questions/19221/find-tangent-point-on-circle-furthest-east-or-west (有点复杂,需要点地理知识的)。在获取包围盒之后还需要如下计算:如果你指定了geo=true(上文说过),你还需要调用 GeoCircleàinit()方法,该方法是确定地理空间中某个圆的圆心的Y坐标(涉及到球面知识较复杂)。至此 SpatialContext.makeCircle()方法执行完毕。

在ShapeReadWriter类 中,如果不是以上的3中形式则程序会报异常,但是在JtsSpatialContext中,则不会报异常,而是会使用WKTReader.read()方 法来生成各种形状,而在使用WKTReader之前需要实例化一个WKTReader,实例化过程需要提供GeometryFactory作为参数传递给 构造方法,而GeometryFactory在构造JtsSpatialContext的时候就已经实例化了,实例化GeometryFactory时需 要提供PrecisionModel,SRID,CoordinateSequenceFactory作为参数,当然实例化WKTReader和 GeometryFactory的工作都是jts的内容,这里就不细讲,以后有机会会专门来学习一下jts的相关东西。实例化了WKTReader之后, 再去调用它的read(str)方法,接下来流程如 下:WKTReader.read(Reader)àWKTReader.readGeometryTaggedText(),在这个方法里就真正开始解 析字符串并形成图形(有 Point,LineString,LinearRing,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection 等形式,它们都继承与Geometry)。执行完read方法后返回的是一个Geometry对象,接下来就根据返回的Geometry具体的形式来判断 是否生成JtsPoint,Rectangle,JtsGeometry。 经纬度——图形至此已经完成。

  1. 图形-->经纬度:

通 过它们的writeShape(Shape)方法实现,writeShape就很简单了,只要获取图形对象的各个坐标值通过字符串拼接返回即可。当然 JtsShapeReadWriter也是比较复杂的,它需要通过WKTWriter来实现。流程 如:WKTWriter.write(Geometry)——WKTWriter.writeFormatted(Geometry geometry,Boolean userFormatting,Writer writer)——实例化DecimalFormat以便对各种数据进行格式化 ——WKTWriter.appendGeometryTaggedText(Geometry geometry,int level,Writer writer),在这个方法里是对各种图形 Point,LineString,LinearRing,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection 进行格式化操作并将字符串返回给Writer。

至此,spatial中将经纬度字符串转化为图形和将图形转化为经纬度字符串就都已经完成,但是JtsSpatialReadWriter提供一种将字节数组转化为图形的方法,该方法将在下篇文章讲解。



Previous     Next
uohzoaix /
Published under (CC) BY-NC-SA in categories spatial  tagged with